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