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