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/main/Tuning.h>
39#include <xrpld/app/misc/AmendmentTable.h>
40#include <xrpld/app/misc/HashRouter.h>
41#include <xrpld/app/misc/LoadFeeTrack.h>
42#include <xrpld/app/misc/NetworkOPs.h>
43#include <xrpld/app/misc/SHAMapStore.h>
44#include <xrpld/app/misc/TxQ.h>
45#include <xrpld/app/misc/ValidatorKeys.h>
46#include <xrpld/app/misc/ValidatorSite.h>
47#include <xrpld/app/paths/PathRequests.h>
48#include <xrpld/app/rdb/RelationalDatabase.h>
49#include <xrpld/app/rdb/Wallet.h>
50#include <xrpld/app/tx/apply.h>
51#include <xrpld/core/DatabaseCon.h>
52#include <xrpld/nodestore/DummyScheduler.h>
53#include <xrpld/overlay/Cluster.h>
54#include <xrpld/overlay/PeerReservationTable.h>
55#include <xrpld/overlay/PeerSet.h>
56#include <xrpld/overlay/make_Overlay.h>
57#include <xrpld/perflog/PerfLog.h>
58#include <xrpld/rpc/detail/RPCHelpers.h>
59#include <xrpld/shamap/NodeFamily.h>
60#include <xrpl/basics/ByteUtilities.h>
61#include <xrpl/basics/ResolverAsio.h>
62#include <xrpl/basics/random.h>
63#include <xrpl/basics/safe_cast.h>
64#include <xrpl/beast/asio/io_latency_probe.h>
65#include <xrpl/beast/core/LexicalCast.h>
66#include <xrpl/crypto/csprng.h>
67#include <xrpl/json/json_reader.h>
68#include <xrpl/protocol/BuildInfo.h>
69#include <xrpl/protocol/Feature.h>
70#include <xrpl/protocol/Protocol.h>
71#include <xrpl/protocol/STParsedJSON.h>
72#include <xrpl/resource/Fees.h>
73
74#include <boost/algorithm/string/predicate.hpp>
75#include <boost/asio/steady_timer.hpp>
76#include <boost/system/error_code.hpp>
77
78#include <date/date.h>
79
80#include <chrono>
81#include <condition_variable>
82#include <cstring>
83#include <iostream>
84#include <limits>
85#include <mutex>
86#include <optional>
87#include <sstream>
88#include <utility>
89#include <variant>
90
91namespace ripple {
92
93static void
94fixConfigPorts(Config& config, Endpoints const& endpoints);
95
96// VFALCO TODO Move the function definitions into the class declaration
97class ApplicationImp : public Application, public BasicApp
98{
99private:
101 {
102 private:
107
108 public:
113 boost::asio::io_service& ios)
114 : m_event(ev)
116 , m_probe(interval, ios)
117 , lastSample_{}
118 {
119 }
120
121 void
123 {
124 m_probe.sample(std::ref(*this));
125 }
126
127 template <class Duration>
128 void
129 operator()(Duration const& elapsed)
130 {
131 using namespace std::chrono;
132 auto const lastSample = ceil<milliseconds>(elapsed);
133
134 lastSample_ = lastSample;
135
136 if (lastSample >= 10ms)
137 m_event.notify(lastSample);
138 if (lastSample >= 500ms)
139 {
140 JLOG(m_journal.warn())
141 << "io_service latency = " << lastSample.count();
142 }
143 }
144
146 get() const
147 {
148 return lastSample_.load();
149 }
150
151 void
153 {
154 m_probe.cancel();
155 }
156
157 void
159 {
161 }
162 };
163
164public:
168
170
174
175 // Required by the SHAMapStore
177
184
189
191
194 // VFALCO TODO Make OrderBookDB abstract
218 boost::asio::steady_timer sweepTimer_;
219 boost::asio::steady_timer entropyTimer_;
220
225
226 boost::asio::signal_set m_signals;
227
228 // Once we get C++20, we could use `std::atomic_flag` for `isTimeToStop`
229 // and eliminate the need for the condition variable and the mutex.
233
235
237
239
241
242 //--------------------------------------------------------------------------
243
244 static std::size_t
246 {
247#if RIPPLE_SINGLE_IO_SERVICE_THREAD
248 return 1;
249#else
250
251 if (config.IO_WORKERS > 0)
252 return config.IO_WORKERS;
253
254 auto const cores = std::thread::hardware_concurrency();
255
256 // Use a single thread when running on under-provisioned systems
257 // or if we are configured to use minimal resources.
258 if ((cores == 1) || ((config.NODE_SIZE == 0) && (cores == 2)))
259 return 1;
260
261 // Otherwise, prefer two threads.
262 return 2;
263#endif
264 }
265
266 //--------------------------------------------------------------------------
267
273 , config_(std::move(config))
274 , logs_(std::move(logs))
275 , timeKeeper_(std::move(timeKeeper))
277 1 +
278 rand_int(
279 crypto_prng(),
280 std::numeric_limits<std::uint64_t>::max() - 1))
281 , m_journal(logs_->journal("Application"))
282
283 // PerfLog must be started before any other threads are launched.
284 , perfLog_(perf::make_PerfLog(
285 perf::setup_PerfLog(
286 config_->section("perf"),
287 config_->CONFIG_DIR),
288 *this,
289 logs_->journal("PerfLog"),
290 [this] { signalStop(); }))
291
292 , m_txMaster(*this)
293
295 config_->section(SECTION_INSIGHT),
296 logs_->journal("Collector")))
297
298 , m_jobQueue(std::make_unique<JobQueue>(
301 return 1;
302
303 if (config->WORKERS)
304 return config->WORKERS;
305
306 auto count =
307 static_cast<int>(std::thread::hardware_concurrency());
308
309 // Be more aggressive about the number of threads to use
310 // for the job queue if the server is configured as "large"
311 // or "huge" if there are enough cores.
312 if (config->NODE_SIZE >= 4 && count >= 16)
313 count = 6 + std::min(count, 8);
314 else if (config->NODE_SIZE >= 3 && count >= 8)
315 count = 4 + std::min(count, 6);
316 else
317 count = 2 + std::min(count, 4);
318
319 return count;
320 }(config_),
321 m_collectorManager->group("jobq"),
322 logs_->journal("JobQueue"),
323 *logs_,
324 *perfLog_))
325
327
329 *this,
331 logs_->journal("SHAMapStore")))
332
334 "NodeCache",
335 16384,
337 stopwatch(),
338 logs_->journal("TaggedCache"))
339
340 , cachedSLEs_(
341 "Cached SLEs",
342 0,
344 stopwatch(),
345 logs_->journal("CachedSLEs"))
346
348
350 m_collectorManager->collector(),
351 logs_->journal("Resource")))
352
353 , m_nodeStore(m_shaMapStore->makeNodeStore(
354 config_->PREFETCH_WORKERS > 0 ? config_->PREFETCH_WORKERS : 4))
355
357
358 , m_orderBookDB(*this)
359
360 , m_pathRequests(std::make_unique<PathRequests>(
361 *this,
362 logs_->journal("PathRequest"),
363 m_collectorManager->collector()))
364
365 , m_ledgerMaster(std::make_unique<LedgerMaster>(
366 *this,
367 stopwatch(),
368 m_collectorManager->collector(),
369 logs_->journal("LedgerMaster")))
370
372 make_LedgerCleaner(*this, logs_->journal("LedgerCleaner")))
373
374 // VFALCO NOTE must come before NetworkOPs to prevent a crash due
375 // to dependencies in the destructor.
376 //
378 *this,
379 stopwatch(),
380 m_collectorManager->collector()))
381
383 *this,
384 m_collectorManager->collector(),
385 [this](std::shared_ptr<SHAMap> const& set, bool fromAcquire) {
386 gotTXSet(set, fromAcquire);
387 }))
388
389 , m_ledgerReplayer(std::make_unique<LedgerReplayer>(
390 *this,
392 make_PeerSetBuilder(*this)))
393
395 "AcceptedLedger",
396 4,
398 stopwatch(),
399 logs_->journal("TaggedCache"))
400
402 *this,
403 stopwatch(),
404 config_->standalone(),
405 config_->NETWORK_QUORUM,
406 config_->START_VALID,
407 *m_jobQueue,
411 logs_->journal("NetworkOPs"),
412 m_collectorManager->collector()))
413
414 , cluster_(std::make_unique<Cluster>(logs_->journal("Overlay")))
415
416 , peerReservations_(std::make_unique<PeerReservationTable>(
417 logs_->journal("PeerReservationTable")))
418
420 std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
421
423 std::make_unique<ManifestCache>(logs_->journal("ManifestCache")))
424
425 , validators_(std::make_unique<ValidatorList>(
429 config_->legacy("database_path"),
430 logs_->journal("ValidatorList"),
431 config_->VALIDATION_QUORUM))
432
433 , validatorSites_(std::make_unique<ValidatorSite>(*this))
434
436 *this,
438 *m_jobQueue,
442
443 , mFeeTrack(
444 std::make_unique<LoadFeeTrack>(logs_->journal("LoadManager")))
445
446 , hashRouter_(std::make_unique<HashRouter>(
447 stopwatch(),
449
450 , mValidations(
451 ValidationParms(),
452 stopwatch(),
453 *this,
454 logs_->journal("Validations"))
455
456 , m_loadManager(make_LoadManager(*this, logs_->journal("LoadManager")))
457
458 , txQ_(
459 std::make_unique<TxQ>(setup_TxQ(*config_), logs_->journal("TxQ")))
460
462
464
466
467 , checkSigs_(true)
468
469 , m_resolver(
470 ResolverAsio::New(get_io_service(), logs_->journal("Resolver")))
471
473 m_collectorManager->collector()->make_event("ios_latency"),
474 logs_->journal("Application"),
477 , grpcServer_(std::make_unique<GRPCServer>(*this))
478 {
480
481 add(m_resourceManager.get());
482
483 //
484 // VFALCO - READ THIS!
485 //
486 // Do not start threads, open sockets, or do any sort of "real work"
487 // inside the constructor. Put it in start instead. Or if you must,
488 // put it in setup (but everything in setup should be moved to start
489 // anyway.
490 //
491 // The reason is that the unit tests require an Application object to
492 // be created. But we don't actually start all the threads, sockets,
493 // and services when running the unit tests. Therefore anything which
494 // needs to be stopped will not get stopped correctly if it is
495 // started in this constructor.
496 //
497
498 add(ledgerCleaner_.get());
499 }
500
501 //--------------------------------------------------------------------------
502
503 bool
504 setup(boost::program_options::variables_map const& cmdline) override;
505 void
506 start(bool withTimers) override;
507 void
508 run() override;
509 void
510 signalStop(std::string msg = "") override;
511 bool
512 checkSigs() const override;
513 void
514 checkSigs(bool) override;
515 bool
516 isStopping() const override;
517 int
518 fdRequired() const override;
519
520 //--------------------------------------------------------------------------
521
523 instanceID() const override
524 {
525 return instanceCookie_;
526 }
527
528 Logs&
529 logs() override
530 {
531 return *logs_;
532 }
533
534 Config&
535 config() override
536 {
537 return *config_;
538 }
539
542 {
543 return *m_collectorManager;
544 }
545
546 Family&
547 getNodeFamily() override
548 {
549 return nodeFamily_;
550 }
551
553 timeKeeper() override
554 {
555 return *timeKeeper_;
556 }
557
558 JobQueue&
559 getJobQueue() override
560 {
561 return *m_jobQueue;
562 }
563
565 nodeIdentity() override
566 {
567 if (nodeIdentity_)
568 return *nodeIdentity_;
569
571 "Accessing Application::nodeIdentity() before it is initialized.");
572 }
573
575 getValidationPublicKey() const override
576 {
577 if (!validatorKeys_.keys)
578 return {};
579
580 return validatorKeys_.keys->publicKey;
581 }
582
584 getOPs() override
585 {
586 return *m_networkOPs;
587 }
588
589 virtual ServerHandler&
591 {
592 XRPL_ASSERT(
594 "ripple::ApplicationImp::getServerHandler : non-null server "
595 "handle");
596 return *serverHandler_;
597 }
598
599 boost::asio::io_service&
600 getIOService() override
601 {
602 return get_io_service();
603 }
604
606 getIOLatency() override
607 {
608 return m_io_latency_sampler.get();
609 }
610
613 {
614 return *m_ledgerMaster;
615 }
616
619 {
620 return *ledgerCleaner_;
621 }
622
625 {
626 return *m_ledgerReplayer;
627 }
628
631 {
632 return *m_inboundLedgers;
633 }
634
637 {
638 return *m_inboundTransactions;
639 }
640
643 {
645 }
646
647 void
648 gotTXSet(std::shared_ptr<SHAMap> const& set, bool fromAcquire)
649 {
650 if (set)
651 m_networkOPs->mapComplete(set, fromAcquire);
652 }
653
656 {
657 return m_txMaster;
658 }
659
661 getPerfLog() override
662 {
663 return *perfLog_;
664 }
665
666 NodeCache&
668 {
669 return m_tempNodeCache;
670 }
671
673 getNodeStore() override
674 {
675 return *m_nodeStore;
676 }
677
679 getMasterMutex() override
680 {
681 return m_masterMutex;
682 }
683
685 getLoadManager() override
686 {
687 return *m_loadManager;
688 }
689
692 {
693 return *m_resourceManager;
694 }
695
697 getOrderBookDB() override
698 {
699 return m_orderBookDB;
700 }
701
704 {
705 return *m_pathRequests;
706 }
707
709 cachedSLEs() override
710 {
711 return cachedSLEs_;
712 }
713
716 {
717 return *m_amendmentTable;
718 }
719
721 getFeeTrack() override
722 {
723 return *mFeeTrack;
724 }
725
727 getHashRouter() override
728 {
729 return *hashRouter_;
730 }
731
733 getValidations() override
734 {
735 return mValidations;
736 }
737
739 validators() override
740 {
741 return *validators_;
742 }
743
745 validatorSites() override
746 {
747 return *validatorSites_;
748 }
749
752 {
753 return *validatorManifests_;
754 }
755
758 {
759 return *publisherManifests_;
760 }
761
762 Cluster&
763 cluster() override
764 {
765 return *cluster_;
766 }
767
770 {
771 return *peerReservations_;
772 }
773
775 getSHAMapStore() override
776 {
777 return *m_shaMapStore;
778 }
779
781 pendingSaves() override
782 {
783 return pendingSaves_;
784 }
785
787 openLedger() override
788 {
789 return *openLedger_;
790 }
791
792 OpenLedger const&
793 openLedger() const override
794 {
795 return *openLedger_;
796 }
797
798 Overlay&
799 overlay() override
800 {
801 XRPL_ASSERT(
802 overlay_, "ripple::ApplicationImp::overlay : non-null overlay");
803 return *overlay_;
804 }
805
806 TxQ&
807 getTxQ() override
808 {
809 XRPL_ASSERT(
810 txQ_,
811 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
812 return *txQ_;
813 }
814
817 {
818 XRPL_ASSERT(
820 "ripple::ApplicationImp::getRelationalDatabase : non-null "
821 "relational database");
822 return *mRelationalDatabase;
823 }
824
826 getWalletDB() override
827 {
828 XRPL_ASSERT(
829 mWalletDB,
830 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
831 return *mWalletDB;
832 }
833
834 bool
835 serverOkay(std::string& reason) override;
836
838 journal(std::string const& name) override;
839
840 //--------------------------------------------------------------------------
841
842 bool
844 {
845 XRPL_ASSERT(
846 mWalletDB.get() == nullptr,
847 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
848 "database");
849
850 try
851 {
854
855 // wallet database
857 setup.useGlobalPragma = false;
858
860 }
861 catch (std::exception const& e)
862 {
863 JLOG(m_journal.fatal())
864 << "Failed to initialize SQL databases: " << e.what();
865 return false;
866 }
867
868 return true;
869 }
870
871 bool
873 {
874 if (config_->doImport)
875 {
876 auto j = logs_->journal("NodeObject");
877 NodeStore::DummyScheduler dummyScheduler;
880 megabytes(config_->getValueFor(
881 SizedItem::burstSize, std::nullopt)),
882 dummyScheduler,
883 0,
885 j);
886
887 JLOG(j.warn()) << "Starting node import from '" << source->getName()
888 << "' to '" << m_nodeStore->getName() << "'.";
889
890 using namespace std::chrono;
891 auto const start = steady_clock::now();
892
893 m_nodeStore->importDatabase(*source);
894
895 auto const elapsed =
896 duration_cast<seconds>(steady_clock::now() - start);
897 JLOG(j.warn()) << "Node import from '" << source->getName()
898 << "' took " << elapsed.count() << " seconds.";
899 }
900
901 return true;
902 }
903
904 //--------------------------------------------------------------------------
905 //
906 // PropertyStream
907 //
908
909 void
911 {
912 }
913
914 //--------------------------------------------------------------------------
915
916 void
918 {
919 // Only start the timer if waitHandlerCounter_ is not yet joined.
920 if (auto optionalCountedHandler = waitHandlerCounter_.wrap(
921 [this](boost::system::error_code const& e) {
922 if (e.value() == boost::system::errc::success)
923 {
924 m_jobQueue->addJob(
925 jtSWEEP, "sweep", [this]() { doSweep(); });
926 }
927 // Recover as best we can if an unexpected error occurs.
928 if (e.value() != boost::system::errc::success &&
929 e.value() != boost::asio::error::operation_aborted)
930 {
931 // Try again later and hope for the best.
932 JLOG(m_journal.error())
933 << "Sweep timer got error '" << e.message()
934 << "'. Restarting timer.";
935 setSweepTimer();
936 }
937 }))
938 {
939 using namespace std::chrono;
940 sweepTimer_.expires_from_now(
941 seconds{config_->SWEEP_INTERVAL.value_or(
942 config_->getValueFor(SizedItem::sweepInterval))});
943 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
944 }
945 }
946
947 void
949 {
950 // Only start the timer if waitHandlerCounter_ is not yet joined.
951 if (auto optionalCountedHandler = waitHandlerCounter_.wrap(
952 [this](boost::system::error_code const& e) {
953 if (e.value() == boost::system::errc::success)
954 {
955 crypto_prng().mix_entropy();
956 setEntropyTimer();
957 }
958 // Recover as best we can if an unexpected error occurs.
959 if (e.value() != boost::system::errc::success &&
960 e.value() != boost::asio::error::operation_aborted)
961 {
962 // Try again later and hope for the best.
963 JLOG(m_journal.error())
964 << "Entropy timer got error '" << e.message()
965 << "'. Restarting timer.";
966 setEntropyTimer();
967 }
968 }))
969 {
970 using namespace std::chrono_literals;
971 entropyTimer_.expires_from_now(5min);
972 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
973 }
974 }
975
976 void
978 {
979 if (!config_->standalone() &&
980 !getRelationalDatabase().transactionDbHasSpace(*config_))
981 {
982 signalStop();
983 }
984
985 // VFALCO NOTE Does the order of calls matter?
986 // VFALCO TODO fix the dependency inversion using an observer,
987 // have listeners register for "onSweep ()" notification.
988
989 {
990 std::shared_ptr<FullBelowCache const> const fullBelowCache =
991 nodeFamily_.getFullBelowCache();
992
993 std::shared_ptr<TreeNodeCache const> const treeNodeCache =
994 nodeFamily_.getTreeNodeCache();
995
996 std::size_t const oldFullBelowSize = fullBelowCache->size();
997 std::size_t const oldTreeNodeSize = treeNodeCache->size();
998
999 nodeFamily_.sweep();
1000
1001 JLOG(m_journal.debug())
1002 << "NodeFamily::FullBelowCache sweep. Size before: "
1003 << oldFullBelowSize
1004 << "; size after: " << fullBelowCache->size();
1005
1006 JLOG(m_journal.debug())
1007 << "NodeFamily::TreeNodeCache sweep. Size before: "
1008 << oldTreeNodeSize << "; size after: " << treeNodeCache->size();
1009 }
1010 {
1011 TaggedCache<uint256, Transaction> const& masterTxCache =
1012 getMasterTransaction().getCache();
1013
1014 std::size_t const oldMasterTxSize = masterTxCache.size();
1015
1016 getMasterTransaction().sweep();
1017
1018 JLOG(m_journal.debug())
1019 << "MasterTransaction sweep. Size before: " << oldMasterTxSize
1020 << "; size after: " << masterTxCache.size();
1021 }
1022 {
1023 // Does not appear to have an associated cache.
1024 getNodeStore().sweep();
1025 }
1026 {
1027 std::size_t const oldLedgerMasterCacheSize =
1028 getLedgerMaster().getFetchPackCacheSize();
1029
1030 getLedgerMaster().sweep();
1031
1032 JLOG(m_journal.debug())
1033 << "LedgerMaster sweep. Size before: "
1034 << oldLedgerMasterCacheSize << "; size after: "
1035 << getLedgerMaster().getFetchPackCacheSize();
1036 }
1037 {
1038 // NodeCache == TaggedCache<SHAMapHash, Blob>
1039 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1040
1041 getTempNodeCache().sweep();
1042
1043 JLOG(m_journal.debug())
1044 << "TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1045 << "; size after: " << getTempNodeCache().size();
1046 }
1047 {
1048 std::size_t const oldCurrentCacheSize =
1049 getValidations().sizeOfCurrentCache();
1050 std::size_t const oldSizeSeqEnforcesSize =
1051 getValidations().sizeOfSeqEnforcersCache();
1052 std::size_t const oldByLedgerSize =
1053 getValidations().sizeOfByLedgerCache();
1054 std::size_t const oldBySequenceSize =
1055 getValidations().sizeOfBySequenceCache();
1056
1057 getValidations().expire(m_journal);
1058
1059 JLOG(m_journal.debug())
1060 << "Validations Current expire. Size before: "
1061 << oldCurrentCacheSize
1062 << "; size after: " << getValidations().sizeOfCurrentCache();
1063
1064 JLOG(m_journal.debug())
1065 << "Validations SeqEnforcer expire. Size before: "
1066 << oldSizeSeqEnforcesSize << "; size after: "
1067 << getValidations().sizeOfSeqEnforcersCache();
1068
1069 JLOG(m_journal.debug())
1070 << "Validations ByLedger expire. Size before: "
1071 << oldByLedgerSize
1072 << "; size after: " << getValidations().sizeOfByLedgerCache();
1073
1074 JLOG(m_journal.debug())
1075 << "Validations BySequence expire. Size before: "
1076 << oldBySequenceSize
1077 << "; size after: " << getValidations().sizeOfBySequenceCache();
1078 }
1079 {
1080 std::size_t const oldInboundLedgersSize =
1081 getInboundLedgers().cacheSize();
1082
1083 getInboundLedgers().sweep();
1084
1085 JLOG(m_journal.debug())
1086 << "InboundLedgers sweep. Size before: "
1087 << oldInboundLedgersSize
1088 << "; size after: " << getInboundLedgers().cacheSize();
1089 }
1090 {
1091 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1092 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1093 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1094
1095 getLedgerReplayer().sweep();
1096
1097 JLOG(m_journal.debug())
1098 << "LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1099 << "; size after: " << getLedgerReplayer().tasksSize();
1100
1101 JLOG(m_journal.debug())
1102 << "LedgerReplayer deltas sweep. Size before: "
1103 << oldDeltasSize
1104 << "; size after: " << getLedgerReplayer().deltasSize();
1105
1106 JLOG(m_journal.debug())
1107 << "LedgerReplayer skipLists sweep. Size before: "
1108 << oldSkipListsSize
1109 << "; size after: " << getLedgerReplayer().skipListsSize();
1110 }
1111 {
1112 std::size_t const oldAcceptedLedgerSize =
1113 m_acceptedLedgerCache.size();
1114
1115 m_acceptedLedgerCache.sweep();
1116
1117 JLOG(m_journal.debug())
1118 << "AcceptedLedgerCache sweep. Size before: "
1119 << oldAcceptedLedgerSize
1120 << "; size after: " << m_acceptedLedgerCache.size();
1121 }
1122 {
1123 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1124
1125 cachedSLEs_.sweep();
1126
1127 JLOG(m_journal.debug())
1128 << "CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1129 << "; size after: " << cachedSLEs_.size();
1130 }
1131
1132 // Set timer to do another sweep later.
1133 setSweepTimer();
1134 }
1135
1138 {
1139 return maxDisallowedLedger_;
1140 }
1141
1142 virtual const std::optional<uint256>&
1143 trapTxID() const override
1144 {
1145 return trapTxID_;
1146 }
1147
1148private:
1149 // For a newly-started validator, this is the greatest persisted ledger
1150 // and new validations must be greater than this.
1151 std::atomic<LedgerIndex> maxDisallowedLedger_{0};
1152
1153 void
1154 startGenesisLedger();
1155
1157 getLastFullLedger();
1158
1160 loadLedgerFromFile(std::string const& ledgerID);
1161
1162 bool
1163 loadOldLedger(
1164 std::string const& ledgerID,
1165 bool replay,
1166 bool isFilename,
1167 std::optional<uint256> trapTxID);
1168
1169 void
1170 setMaxDisallowedLedger();
1171};
1172
1173//------------------------------------------------------------------------------
1174
1175// TODO Break this up into smaller, more digestible initialization segments.
1176bool
1177ApplicationImp::setup(boost::program_options::variables_map const& cmdline)
1178{
1179 // We want to intercept CTRL-C and the standard termination signal SIGTERM
1180 // and terminate the process. This handler will NEVER be invoked twice.
1181 //
1182 // Note that async_wait is "one-shot": for each call, the handler will be
1183 // invoked exactly once, either when one of the registered signals in the
1184 // signal set occurs or the signal set is cancelled. Subsequent signals are
1185 // effectively ignored (technically, they are queued up, waiting for a call
1186 // to async_wait).
1187 m_signals.add(SIGINT);
1188 m_signals.add(SIGTERM);
1189 m_signals.async_wait(
1190 [this](boost::system::error_code const& ec, int signum) {
1191 // Indicates the signal handler has been aborted; do nothing
1192 if (ec == boost::asio::error::operation_aborted)
1193 return;
1194
1195 JLOG(m_journal.info()) << "Received signal " << signum;
1196
1197 if (signum == SIGTERM || signum == SIGINT)
1198 signalStop();
1199 });
1200
1201 auto debug_log = config_->getDebugLogFile();
1202
1203 if (!debug_log.empty())
1204 {
1205 // Let debug messages go to the file but only WARNING or higher to
1206 // regular output (unless verbose)
1207
1208 if (!logs_->open(debug_log))
1209 std::cerr << "Can't open log file " << debug_log << '\n';
1210
1211 using namespace beast::severities;
1212 if (logs_->threshold() > kDebug)
1213 logs_->threshold(kDebug);
1214 }
1215
1216 JLOG(m_journal.info()) << "Process starting: "
1217 << BuildInfo::getFullVersionString()
1218 << ", Instance Cookie: " << instanceCookie_;
1219
1220 if (numberOfThreads(*config_) < 2)
1221 {
1222 JLOG(m_journal.warn()) << "Limited to a single I/O service thread by "
1223 "system configuration.";
1224 }
1225
1226 // Optionally turn off logging to console.
1227 logs_->silent(config_->silent());
1228
1229 if (!initRelationalDatabase() || !initNodeStore())
1230 return false;
1231
1232 if (!peerReservations_->load(getWalletDB()))
1233 {
1234 JLOG(m_journal.fatal()) << "Cannot find peer reservations!";
1235 return false;
1236 }
1237
1238 if (validatorKeys_.keys)
1239 setMaxDisallowedLedger();
1240
1241 // Configure the amendments the server supports
1242 {
1243 auto const supported = []() {
1244 auto const& amendments = detail::supportedAmendments();
1246 supported.reserve(amendments.size());
1247 for (auto const& [a, vote] : amendments)
1248 {
1249 auto const f = ripple::getRegisteredFeature(a);
1250 XRPL_ASSERT(
1251 f, "ripple::ApplicationImp::setup : registered feature");
1252 if (f)
1253 supported.emplace_back(a, *f, vote);
1254 }
1255 return supported;
1256 }();
1257 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1258
1259 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1260
1261 m_amendmentTable = make_AmendmentTable(
1262 *this,
1263 config().AMENDMENT_MAJORITY_TIME,
1264 supported,
1265 upVoted,
1266 downVoted,
1267 logs_->journal("Amendments"));
1268 }
1269
1270 Pathfinder::initPathTable();
1271
1272 auto const startUp = config_->START_UP;
1273 JLOG(m_journal.debug()) << "startUp: " << startUp;
1274 if (startUp == Config::FRESH)
1275 {
1276 JLOG(m_journal.info()) << "Starting new Ledger";
1277
1278 startGenesisLedger();
1279 }
1280 else if (
1281 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1282 startUp == Config::REPLAY)
1283 {
1284 JLOG(m_journal.info()) << "Loading specified Ledger";
1285
1286 if (!loadOldLedger(
1287 config_->START_LEDGER,
1288 startUp == Config::REPLAY,
1289 startUp == Config::LOAD_FILE,
1290 config_->TRAP_TX_HASH))
1291 {
1292 JLOG(m_journal.error())
1293 << "The specified ledger could not be loaded.";
1294 if (config_->FAST_LOAD)
1295 {
1296 // Fall back to syncing from the network, such as
1297 // when there's no existing data.
1298 startGenesisLedger();
1299 }
1300 else
1301 {
1302 return false;
1303 }
1304 }
1305 }
1306 else if (startUp == Config::NETWORK)
1307 {
1308 // This should probably become the default once we have a stable
1309 // network.
1310 if (!config_->standalone())
1311 m_networkOPs->setNeedNetworkLedger();
1312
1313 startGenesisLedger();
1314 }
1315 else
1316 {
1317 startGenesisLedger();
1318 }
1319
1320 if (auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1321 {
1322 m_ledgerMaster->setLedgerRangePresent(
1323 forcedRange->first, forcedRange->second);
1324 }
1325
1326 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1327
1328 nodeIdentity_ = getNodeIdentity(*this, cmdline);
1329
1330 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1331 {
1332 JLOG(m_journal.fatal()) << "Invalid entry in cluster configuration.";
1333 return false;
1334 }
1335
1336 {
1337 if (validatorKeys_.configInvalid())
1338 return false;
1339
1340 if (!validatorManifests_->load(
1341 getWalletDB(),
1342 "ValidatorManifests",
1343 validatorKeys_.manifest,
1344 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1345 {
1346 JLOG(m_journal.fatal()) << "Invalid configured validator manifest.";
1347 return false;
1348 }
1349
1350 publisherManifests_->load(getWalletDB(), "PublisherManifests");
1351
1352 // It is possible to have a valid ValidatorKeys object without
1353 // setting the signingKey or masterKey. This occurs if the
1354 // configuration file does not have either
1355 // SECTION_VALIDATOR_TOKEN or SECTION_VALIDATION_SEED section.
1356
1357 // masterKey for the configuration-file specified validator keys
1358 std::optional<PublicKey> localSigningKey;
1359 if (validatorKeys_.keys)
1360 localSigningKey = validatorKeys_.keys->publicKey;
1361
1362 // Setup trusted validators
1363 if (!validators_->load(
1364 localSigningKey,
1365 config().section(SECTION_VALIDATORS).values(),
1366 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1367 config().VALIDATOR_LIST_THRESHOLD))
1368 {
1369 JLOG(m_journal.fatal())
1370 << "Invalid entry in validator configuration.";
1371 return false;
1372 }
1373 }
1374
1375 if (!validatorSites_->load(
1376 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1377 {
1378 JLOG(m_journal.fatal())
1379 << "Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES << "]";
1380 return false;
1381 }
1382
1383 // Tell the AmendmentTable who the trusted validators are.
1384 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1385
1386 //----------------------------------------------------------------------
1387 //
1388 // Server
1389 //
1390 //----------------------------------------------------------------------
1391
1392 // VFALCO NOTE Unfortunately, in stand-alone mode some code still
1393 // foolishly calls overlay(). When this is fixed we can
1394 // move the instantiation inside a conditional:
1395 //
1396 // if (!config_.standalone())
1397 overlay_ = make_Overlay(
1398 *this,
1399 setup_Overlay(*config_),
1400 *serverHandler_,
1401 *m_resourceManager,
1402 *m_resolver,
1403 get_io_service(),
1404 *config_,
1405 m_collectorManager->collector());
1406 add(*overlay_); // add to PropertyStream
1407
1408 // start first consensus round
1409 if (!m_networkOPs->beginConsensus(
1410 m_ledgerMaster->getClosedLedger()->info().hash, {}))
1411 {
1412 JLOG(m_journal.fatal()) << "Unable to start consensus";
1413 return false;
1414 }
1415
1416 {
1417 try
1418 {
1419 auto setup = setup_ServerHandler(
1420 *config_, beast::logstream{m_journal.error()});
1421 setup.makeContexts();
1422 serverHandler_->setup(setup, m_journal);
1423 fixConfigPorts(*config_, serverHandler_->endpoints());
1424 }
1425 catch (std::exception const& e)
1426 {
1427 if (auto stream = m_journal.fatal())
1428 {
1429 stream << "Unable to setup server handler";
1430 if (std::strlen(e.what()) > 0)
1431 stream << ": " << e.what();
1432 }
1433 return false;
1434 }
1435 }
1436
1437 // Begin connecting to network.
1438 if (!config_->standalone())
1439 {
1440 // Should this message be here, conceptually? In theory this sort
1441 // of message, if displayed, should be displayed from PeerFinder.
1442 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1443 {
1444 JLOG(m_journal.warn())
1445 << "No outbound peer connections will be made";
1446 }
1447
1448 // VFALCO NOTE the state timer resets the deadlock detector.
1449 //
1450 m_networkOPs->setStateTimer();
1451 }
1452 else
1453 {
1454 JLOG(m_journal.warn()) << "Running in standalone mode";
1455
1456 m_networkOPs->setStandAlone();
1457 }
1458
1459 if (config_->canSign())
1460 {
1461 JLOG(m_journal.warn()) << "*** The server is configured to allow the "
1462 "'sign' and 'sign_for'";
1463 JLOG(m_journal.warn()) << "*** commands. These commands have security "
1464 "implications and have";
1465 JLOG(m_journal.warn()) << "*** been deprecated. They will be removed "
1466 "in a future release of";
1467 JLOG(m_journal.warn()) << "*** rippled.";
1468 JLOG(m_journal.warn()) << "*** If you do not use them to sign "
1469 "transactions please edit your";
1470 JLOG(m_journal.warn())
1471 << "*** configuration file and remove the [enable_signing] stanza.";
1472 JLOG(m_journal.warn()) << "*** If you do use them to sign transactions "
1473 "please migrate to a";
1474 JLOG(m_journal.warn())
1475 << "*** standalone signing solution as soon as possible.";
1476 }
1477
1478 //
1479 // Execute start up rpc commands.
1480 //
1481 for (auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1482 {
1483 Json::Reader jrReader;
1484 Json::Value jvCommand;
1485
1486 if (!jrReader.parse(cmd, jvCommand))
1487 {
1488 JLOG(m_journal.fatal()) << "Couldn't parse entry in ["
1489 << SECTION_RPC_STARTUP << "]: '" << cmd;
1490 }
1491
1492 if (!config_->quiet())
1493 {
1494 JLOG(m_journal.fatal())
1495 << "Startup RPC: " << jvCommand << std::endl;
1496 }
1497
1498 Resource::Charge loadType = Resource::feeReferenceRPC;
1500 RPC::JsonContext context{
1501 {journal("RPCHandler"),
1502 *this,
1503 loadType,
1504 getOPs(),
1505 getLedgerMaster(),
1506 c,
1507 Role::ADMIN,
1508 {},
1509 {},
1510 RPC::apiMaximumSupportedVersion},
1511 jvCommand};
1512
1513 Json::Value jvResult;
1514 RPC::doCommand(context, jvResult);
1515
1516 if (!config_->quiet())
1517 {
1518 JLOG(m_journal.fatal()) << "Result: " << jvResult << std::endl;
1519 }
1520 }
1521
1522 validatorSites_->start();
1523
1524 return true;
1525}
1526
1527void
1528ApplicationImp::start(bool withTimers)
1529{
1530 JLOG(m_journal.info()) << "Application starting. Version is "
1531 << BuildInfo::getVersionString();
1532
1533 if (withTimers)
1534 {
1535 setSweepTimer();
1536 setEntropyTimer();
1537 }
1538
1539 m_io_latency_sampler.start();
1540 m_resolver->start();
1541 m_loadManager->start();
1542 m_shaMapStore->start();
1543 if (overlay_)
1544 overlay_->start();
1545
1546 if (grpcServer_->start())
1548 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1549
1550 ledgerCleaner_->start();
1551 perfLog_->start();
1552}
1553
1554void
1555ApplicationImp::run()
1556{
1557 if (!config_->standalone())
1558 {
1559 // VFALCO NOTE This seems unnecessary. If we properly refactor the load
1560 // manager then the deadlock detector can just always be
1561 // "armed"
1562 //
1563 getLoadManager().activateDeadlockDetector();
1564 }
1565
1566 {
1567 std::unique_lock<std::mutex> lk{stoppingMutex_};
1568 stoppingCondition_.wait(lk, [this] { return isTimeToStop.load(); });
1569 }
1570
1571 JLOG(m_journal.debug()) << "Application stopping";
1572
1573 m_io_latency_sampler.cancel_async();
1574
1575 // VFALCO Enormous hack, we have to force the probe to cancel
1576 // before we stop the io_service queue or else it never
1577 // unblocks in its destructor. The fix is to make all
1578 // io_objects gracefully handle exit so that we can
1579 // naturally return from io_service::run() instead of
1580 // forcing a call to io_service::stop()
1581 m_io_latency_sampler.cancel();
1582
1583 m_resolver->stop_async();
1584
1585 // NIKB This is a hack - we need to wait for the resolver to
1586 // stop. before we stop the io_server_queue or weird
1587 // things will happen.
1588 m_resolver->stop();
1589
1590 {
1591 boost::system::error_code ec;
1592 sweepTimer_.cancel(ec);
1593 if (ec)
1594 {
1595 JLOG(m_journal.error())
1596 << "Application: sweepTimer cancel error: " << ec.message();
1597 }
1598
1599 ec.clear();
1600 entropyTimer_.cancel(ec);
1601 if (ec)
1602 {
1603 JLOG(m_journal.error())
1604 << "Application: entropyTimer cancel error: " << ec.message();
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
1713 std::shared_ptr<Ledger> const genesis = std::make_shared<Ledger>(
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
1940 auto il = std::make_shared<InboundLedger>(
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
1984 auto il = std::make_shared<InboundLedger>(
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 JLOG(m_journal.fatal()) << "Replay ledger missing/damaged";
1998 UNREACHABLE(
1999 "ripple::ApplicationImp::loadOldLedger : replay ledger "
2000 "missing/damaged");
2001 return false;
2002 }
2003 }
2004 }
2005 using namespace std::chrono_literals;
2006 using namespace date;
2007 static constexpr NetClock::time_point ledgerWarnTimePoint{
2008 sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}};
2009 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
2010 {
2011 JLOG(m_journal.fatal())
2012 << "\n\n*** WARNING ***\n"
2013 "You are replaying a ledger from before "
2014 << to_string(ledgerWarnTimePoint)
2015 << " UTC.\n"
2016 "This replay will not handle your ledger as it was "
2017 "originally "
2018 "handled.\nConsider running an earlier version of rippled "
2019 "to "
2020 "get the older rules.\n*** CONTINUING ***\n";
2021 }
2022
2023 JLOG(m_journal.info()) << "Loading ledger " << loadLedger->info().hash
2024 << " seq:" << loadLedger->info().seq;
2025
2026 if (loadLedger->info().accountHash.isZero())
2027 {
2028 JLOG(m_journal.fatal()) << "Ledger is empty.";
2029 UNREACHABLE(
2030 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2031 return false;
2032 }
2033
2034 if (!loadLedger->walkLedger(journal("Ledger"), true))
2035 {
2036 JLOG(m_journal.fatal()) << "Ledger is missing nodes.";
2037 UNREACHABLE(
2038 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2039 "nodes");
2040 return false;
2041 }
2042
2043 if (!loadLedger->assertSensible(journal("Ledger")))
2044 {
2045 JLOG(m_journal.fatal()) << "Ledger is not sensible.";
2046 UNREACHABLE(
2047 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2048 "sensible");
2049 return false;
2050 }
2051
2052 m_ledgerMaster->setLedgerRangePresent(
2053 loadLedger->info().seq, loadLedger->info().seq);
2054
2055 m_ledgerMaster->switchLCL(loadLedger);
2056 loadLedger->setValidated();
2057 m_ledgerMaster->setFullLedger(loadLedger, true, false);
2058 openLedger_.emplace(
2059 loadLedger, cachedSLEs_, logs_->journal("OpenLedger"));
2060
2061 if (replay)
2062 {
2063 // inject transaction(s) from the replayLedger into our open ledger
2064 // and build replay structure
2065 auto replayData =
2066 std::make_unique<LedgerReplay>(loadLedger, replayLedger);
2067
2068 for (auto const& [_, tx] : replayData->orderedTxns())
2069 {
2070 (void)_;
2071 auto txID = tx->getTransactionID();
2072 if (trapTxID == txID)
2073 {
2074 trapTxID_ = txID;
2075 JLOG(m_journal.debug()) << "Trap transaction set: " << txID;
2076 }
2077
2078 auto s = std::make_shared<Serializer>();
2079 tx->add(*s);
2080
2081 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2082
2083 openLedger_->modify(
2084 [&txID, &s](OpenView& view, beast::Journal j) {
2085 view.rawTxInsert(txID, std::move(s), nullptr);
2086 return true;
2087 });
2088 }
2089
2090 m_ledgerMaster->takeReplay(std::move(replayData));
2091
2092 if (trapTxID && !trapTxID_)
2093 {
2094 JLOG(m_journal.fatal())
2095 << "Ledger " << replayLedger->info().seq
2096 << " does not contain the transaction hash " << *trapTxID;
2097 return false;
2098 }
2099 }
2100 }
2101 catch (SHAMapMissingNode const& mn)
2102 {
2103 JLOG(m_journal.fatal())
2104 << "While loading specified ledger: " << mn.what();
2105 return false;
2106 }
2107 catch (boost::bad_lexical_cast&)
2108 {
2109 JLOG(m_journal.fatal())
2110 << "Ledger specified '" << ledgerID << "' is not valid";
2111 return false;
2112 }
2113
2114 return true;
2115}
2116
2117bool
2118ApplicationImp::serverOkay(std::string& reason)
2119{
2120 if (!config().ELB_SUPPORT)
2121 return true;
2122
2123 if (isStopping())
2124 {
2125 reason = "Server is shutting down";
2126 return false;
2127 }
2128
2129 if (getOPs().isNeedNetworkLedger())
2130 {
2131 reason = "Not synchronized with network yet";
2132 return false;
2133 }
2134
2135 if (getOPs().isAmendmentBlocked())
2136 {
2137 reason = "Server version too old";
2138 return false;
2139 }
2140
2141 if (getOPs().isUNLBlocked())
2142 {
2143 reason = "No valid validator list available";
2144 return false;
2145 }
2146
2147 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2148 {
2149 reason = "Not synchronized with network";
2150 return false;
2151 }
2152
2153 if (!getLedgerMaster().isCaughtUp(reason))
2154 return false;
2155
2156 if (getFeeTrack().isLoadedLocal())
2157 {
2158 reason = "Too much load";
2159 return false;
2160 }
2161
2162 return true;
2163}
2164
2166ApplicationImp::journal(std::string const& name)
2167{
2168 return logs_->journal(name);
2169}
2170
2171void
2172ApplicationImp::setMaxDisallowedLedger()
2173{
2174 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2175 if (seq)
2176 maxDisallowedLedger_ = *seq;
2177
2178 JLOG(m_journal.trace())
2179 << "Max persisted ledger is " << maxDisallowedLedger_;
2180}
2181
2182//------------------------------------------------------------------------------
2183
2184Application::Application() : beast::PropertyStream::Source("app")
2185{
2186}
2187
2188//------------------------------------------------------------------------------
2189
2194 std::unique_ptr<TimeKeeper> timeKeeper)
2195{
2196 return std::make_unique<ApplicationImp>(
2197 std::move(config), std::move(logs), std::move(timeKeeper));
2198}
2199
2200void
2201fixConfigPorts(Config& config, Endpoints const& endpoints)
2202{
2203 for (auto const& [name, ep] : endpoints)
2204 {
2205 if (!config.exists(name))
2206 continue;
2207
2208 auto& section = config[name];
2209 auto const optPort = section.get("port");
2210 if (optPort)
2211 {
2212 std::uint16_t const port =
2213 beast::lexicalCast<std::uint16_t>(*optPort);
2214 if (!port)
2215 section.set("port", std::to_string(ep.port()));
2216 }
2217 }
2218}
2219
2220} // namespace ripple
boost::asio::io_service & get_io_service()
Definition: BasicApp.h:41
Unserialize a JSON document into a Value.
Definition: json_reader.h:37
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:73
Represents a JSON value.
Definition: json_value.h:147
bool isObjectOrNull() const
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:916
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:469
A generic endpoint for log messages.
Definition: Journal.h:59
Stream fatal() const
Definition: Journal.h:351
Stream warn() const
Definition: Journal.h:339
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:242
bool FORCE_MULTI_THREAD
Definition: Config.h:246
bool standalone() const
Definition: Config.h:344
std::size_t NODE_SIZE
Definition: Config.h:220
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:56
Check the ledger/transaction databases to make sure they have continuity.
Definition: LedgerCleaner.h:33
Manages the lifetime of ledger replay tasks.
Manages the current fee schedule.
Definition: LoadFeeTrack.h:46
Manages load sources.
Definition: LoadManager.h:46
Manages partitions for logging.
Definition: Log.h:49
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:50
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:52
Keeps track of which ledgers haven't been fully saved.
Definition: PendingSaves.h:37
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:32
std::optional< STObject > object
The STObject if the parse was successful.
Definition: STParsedJSON.h:50
Holds a collection of configuration values.
Definition: BasicConfig.h:46
std::size_t size() const
Returns the number of items in the container.
Definition: TaggedCache.h:98
Manages various times used by the server.
Definition: TimeKeeper.h:32
Transaction Queue.
Definition: TxQ.h:58
Validator keys and manifest as set in configuration file.
Definition: ValidatorKeys.h:37
std::optional< Keys > keys
Definition: ValidatorKeys.h:62
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition: base_uint.h:502
bool isZero() const
Definition: base_uint.h:539
Singleton class that maintains performance counters and optionally writes Json-formatted data to a di...
Definition: PerfLog.h:49
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:29
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition: LexicalCast.h:201
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:1112
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:1122
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:99
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:99
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:1135
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:120
std::optional< uint256 > getRegisteredFeature(std::string const &name)
Definition: Feature.cpp:376
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
Definition: Wallet.cpp:26
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:60
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:48
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)