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>
74#include <boost/algorithm/string/predicate.hpp>
75#include <boost/asio/steady_timer.hpp>
76#include <boost/system/error_code.hpp>
113 boost::asio::io_service& ios)
127 template <
class Duration>
132 auto const lastSample = ceil<milliseconds>(elapsed);
136 if (lastSample >= 10ms)
138 if (lastSample >= 500ms)
141 <<
"io_service latency = " << lastSample.count();
247#if RIPPLE_SINGLE_IO_SERVICE_THREAD
295 config_->section(SECTION_INSIGHT),
296 logs_->journal(
"Collector")))
322 logs_->journal(
"JobQueue"),
331 logs_->journal(
"SHAMapStore")))
338 logs_->journal(
"TaggedCache"))
345 logs_->journal(
"CachedSLEs"))
351 logs_->journal(
"Resource")))
362 logs_->journal(
"PathRequest"),
369 logs_->journal(
"LedgerMaster")))
386 gotTXSet(set, fromAcquire);
399 logs_->journal(
"TaggedCache"))
411 logs_->journal(
"NetworkOPs"),
414 ,
cluster_(std::make_unique<Cluster>(
logs_->journal(
"Overlay")))
417 logs_->journal(
"PeerReservationTable")))
420 std::make_unique<ManifestCache>(
logs_->journal(
"ManifestCache")))
423 std::make_unique<ManifestCache>(
logs_->journal(
"ManifestCache")))
429 config_->legacy(
"database_path"),
430 logs_->journal(
"ValidatorList"),
444 std::make_unique<LoadFeeTrack>(
logs_->journal(
"LoadManager")))
454 logs_->journal(
"Validations"))
474 logs_->journal(
"Application"),
504 setup(boost::program_options::variables_map
const& cmdline)
override;
506 start(
bool withTimers)
override;
571 "Accessing Application::nodeIdentity() before it is initialized.");
594 "ripple::ApplicationImp::getServerHandler : non-null server "
599 boost::asio::io_service&
802 overlay_,
"ripple::ApplicationImp::overlay : non-null overlay");
811 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
820 "ripple::ApplicationImp::getRelationalDatabase : non-null "
821 "relational database");
830 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
847 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
857 setup.useGlobalPragma =
false;
864 <<
"Failed to initialize SQL databases: " << e.
what();
876 auto j =
logs_->journal(
"NodeObject");
887 JLOG(j.warn()) <<
"Starting node import from '" << source->getName()
891 auto const start = steady_clock::now();
896 duration_cast<seconds>(steady_clock::now() -
start);
897 JLOG(j.warn()) <<
"Node import from '" << source->getName()
898 <<
"' took " << elapsed.count() <<
" seconds.";
921 [
this](boost::system::error_code
const& e) {
922 if (e.value() == boost::system::errc::success)
925 jtSWEEP,
"sweep", [this]() { doSweep(); });
928 if (e.value() != boost::system::errc::success &&
929 e.value() != boost::asio::error::operation_aborted)
932 JLOG(m_journal.error())
933 <<
"Sweep timer got error '" << e.message()
934 <<
"'. Restarting timer.";
943 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
951 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
952 [
this](boost::system::error_code
const& e) {
953 if (e.value() == boost::system::errc::success)
955 crypto_prng().mix_entropy();
959 if (e.value() != boost::system::errc::success &&
960 e.value() != boost::asio::error::operation_aborted)
963 JLOG(m_journal.error())
964 <<
"Entropy timer got error '" << e.message()
965 <<
"'. Restarting timer.";
970 using namespace std::chrono_literals;
971 entropyTimer_.expires_from_now(5min);
972 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
979 if (!config_->standalone() &&
980 !getRelationalDatabase().transactionDbHasSpace(*config_))
991 nodeFamily_.getFullBelowCache();
994 nodeFamily_.getTreeNodeCache();
996 std::size_t const oldFullBelowSize = fullBelowCache->size();
997 std::size_t const oldTreeNodeSize = treeNodeCache->size();
1001 JLOG(m_journal.debug())
1002 <<
"NodeFamily::FullBelowCache sweep. Size before: "
1004 <<
"; size after: " << fullBelowCache->size();
1006 JLOG(m_journal.debug())
1007 <<
"NodeFamily::TreeNodeCache sweep. Size before: "
1008 << oldTreeNodeSize <<
"; size after: " << treeNodeCache->size();
1012 getMasterTransaction().getCache();
1016 getMasterTransaction().sweep();
1018 JLOG(m_journal.debug())
1019 <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
1020 <<
"; size after: " << masterTxCache.
size();
1024 getNodeStore().sweep();
1028 getLedgerMaster().getFetchPackCacheSize();
1030 getLedgerMaster().sweep();
1032 JLOG(m_journal.debug())
1033 <<
"LedgerMaster sweep. Size before: "
1034 << oldLedgerMasterCacheSize <<
"; size after: "
1035 << getLedgerMaster().getFetchPackCacheSize();
1039 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1041 getTempNodeCache().sweep();
1043 JLOG(m_journal.debug())
1044 <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1045 <<
"; size after: " << getTempNodeCache().size();
1049 getValidations().sizeOfCurrentCache();
1051 getValidations().sizeOfSeqEnforcersCache();
1053 getValidations().sizeOfByLedgerCache();
1055 getValidations().sizeOfBySequenceCache();
1057 getValidations().expire(m_journal);
1059 JLOG(m_journal.debug())
1060 <<
"Validations Current expire. Size before: "
1061 << oldCurrentCacheSize
1062 <<
"; size after: " << getValidations().sizeOfCurrentCache();
1064 JLOG(m_journal.debug())
1065 <<
"Validations SeqEnforcer expire. Size before: "
1066 << oldSizeSeqEnforcesSize <<
"; size after: "
1067 << getValidations().sizeOfSeqEnforcersCache();
1069 JLOG(m_journal.debug())
1070 <<
"Validations ByLedger expire. Size before: "
1072 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1074 JLOG(m_journal.debug())
1075 <<
"Validations BySequence expire. Size before: "
1076 << oldBySequenceSize
1077 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1081 getInboundLedgers().cacheSize();
1083 getInboundLedgers().sweep();
1085 JLOG(m_journal.debug())
1086 <<
"InboundLedgers sweep. Size before: "
1087 << oldInboundLedgersSize
1088 <<
"; size after: " << getInboundLedgers().cacheSize();
1091 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1092 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1093 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1095 getLedgerReplayer().sweep();
1097 JLOG(m_journal.debug())
1098 <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1099 <<
"; size after: " << getLedgerReplayer().tasksSize();
1101 JLOG(m_journal.debug())
1102 <<
"LedgerReplayer deltas sweep. Size before: "
1104 <<
"; size after: " << getLedgerReplayer().deltasSize();
1106 JLOG(m_journal.debug())
1107 <<
"LedgerReplayer skipLists sweep. Size before: "
1109 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1113 m_acceptedLedgerCache.size();
1115 m_acceptedLedgerCache.sweep();
1117 JLOG(m_journal.debug())
1118 <<
"AcceptedLedgerCache sweep. Size before: "
1119 << oldAcceptedLedgerSize
1120 <<
"; size after: " << m_acceptedLedgerCache.size();
1123 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1125 cachedSLEs_.sweep();
1127 JLOG(m_journal.debug())
1128 <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1129 <<
"; size after: " << cachedSLEs_.size();
1139 return maxDisallowedLedger_;
1154 startGenesisLedger();
1157 getLastFullLedger();
1170 setMaxDisallowedLedger();
1177ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1187 m_signals.add(SIGINT);
1188 m_signals.add(SIGTERM);
1189 m_signals.async_wait(
1190 [
this](boost::system::error_code
const& ec,
int signum) {
1192 if (ec == boost::asio::error::operation_aborted)
1195 JLOG(m_journal.info()) <<
"Received signal " << signum;
1197 if (signum == SIGTERM || signum == SIGINT)
1201 auto debug_log = config_->getDebugLogFile();
1203 if (!debug_log.empty())
1208 if (!logs_->open(debug_log))
1209 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1212 if (logs_->threshold() > kDebug)
1213 logs_->threshold(kDebug);
1216 JLOG(m_journal.info()) <<
"Process starting: "
1217 << BuildInfo::getFullVersionString()
1218 <<
", Instance Cookie: " << instanceCookie_;
1220 if (numberOfThreads(*config_) < 2)
1222 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1223 "system configuration.";
1227 logs_->silent(config_->silent());
1229 if (!initRelationalDatabase() || !initNodeStore())
1232 if (!peerReservations_->load(getWalletDB()))
1234 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1238 if (validatorKeys_.keys)
1239 setMaxDisallowedLedger();
1243 auto const supported = []() {
1244 auto const& amendments = detail::supportedAmendments();
1246 supported.reserve(amendments.size());
1247 for (
auto const& [a, vote] : amendments)
1251 f,
"ripple::ApplicationImp::setup : registered feature");
1253 supported.emplace_back(a, *f, vote);
1257 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1259 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1263 config().AMENDMENT_MAJORITY_TIME,
1267 logs_->journal(
"Amendments"));
1270 Pathfinder::initPathTable();
1272 auto const startUp = config_->START_UP;
1273 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1274 if (startUp == Config::FRESH)
1276 JLOG(m_journal.info()) <<
"Starting new Ledger";
1278 startGenesisLedger();
1281 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1282 startUp == Config::REPLAY)
1284 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1287 config_->START_LEDGER,
1288 startUp == Config::REPLAY,
1289 startUp == Config::LOAD_FILE,
1290 config_->TRAP_TX_HASH))
1292 JLOG(m_journal.error())
1293 <<
"The specified ledger could not be loaded.";
1294 if (config_->FAST_LOAD)
1298 startGenesisLedger();
1306 else if (startUp == Config::NETWORK)
1310 if (!config_->standalone())
1311 m_networkOPs->setNeedNetworkLedger();
1313 startGenesisLedger();
1317 startGenesisLedger();
1320 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1322 m_ledgerMaster->setLedgerRangePresent(
1323 forcedRange->first, forcedRange->second);
1326 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1330 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1332 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1337 if (validatorKeys_.configInvalid())
1340 if (!validatorManifests_->load(
1342 "ValidatorManifests",
1343 validatorKeys_.manifest,
1344 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1346 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1350 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1359 if (validatorKeys_.keys)
1360 localSigningKey = validatorKeys_.keys->publicKey;
1363 if (!validators_->load(
1365 config().section(SECTION_VALIDATORS).values(),
1366 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1367 config().VALIDATOR_LIST_THRESHOLD))
1369 JLOG(m_journal.fatal())
1370 <<
"Invalid entry in validator configuration.";
1375 if (!validatorSites_->load(
1376 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1378 JLOG(m_journal.fatal())
1379 <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1384 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1405 m_collectorManager->collector());
1409 if (!m_networkOPs->beginConsensus(
1410 m_ledgerMaster->getClosedLedger()->info().hash, {}))
1412 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1422 serverHandler_->setup(setup, m_journal);
1427 if (
auto stream = m_journal.fatal())
1429 stream <<
"Unable to setup server handler";
1431 stream <<
": " << e.
what();
1438 if (!config_->standalone())
1442 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1444 JLOG(m_journal.warn())
1445 <<
"No outbound peer connections will be made";
1450 m_networkOPs->setStateTimer();
1454 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1456 m_networkOPs->setStandAlone();
1459 if (config_->canSign())
1461 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1462 "'sign' and 'sign_for'";
1463 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1464 "implications and have";
1465 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1466 "in a future release of";
1467 JLOG(m_journal.warn()) <<
"*** rippled.";
1468 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1469 "transactions please edit your";
1470 JLOG(m_journal.warn())
1471 <<
"*** configuration file and remove the [enable_signing] stanza.";
1472 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1473 "please migrate to a";
1474 JLOG(m_journal.warn())
1475 <<
"*** standalone signing solution as soon as possible.";
1481 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1486 if (!jrReader.
parse(cmd, jvCommand))
1488 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in ["
1489 << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1492 if (!config_->quiet())
1494 JLOG(m_journal.fatal())
1495 <<
"Startup RPC: " << jvCommand <<
std::endl;
1501 {journal(
"RPCHandler"),
1510 RPC::apiMaximumSupportedVersion},
1514 RPC::doCommand(context, jvResult);
1516 if (!config_->quiet())
1518 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1522 validatorSites_->start();
1528ApplicationImp::start(
bool withTimers)
1530 JLOG(m_journal.info()) <<
"Application starting. Version is "
1531 << BuildInfo::getVersionString();
1539 m_io_latency_sampler.start();
1540 m_resolver->start();
1541 m_loadManager->start();
1542 m_shaMapStore->start();
1546 if (grpcServer_->start())
1548 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1550 ledgerCleaner_->start();
1555ApplicationImp::run()
1557 if (!config_->standalone())
1563 getLoadManager().activateDeadlockDetector();
1568 stoppingCondition_.wait(lk, [
this] {
return isTimeToStop.load(); });
1571 JLOG(m_journal.debug()) <<
"Application stopping";
1573 m_io_latency_sampler.cancel_async();
1581 m_io_latency_sampler.cancel();
1583 m_resolver->stop_async();
1591 boost::system::error_code ec;
1592 sweepTimer_.cancel(ec);
1595 JLOG(m_journal.error())
1596 <<
"Application: sweepTimer cancel error: " << ec.message();
1600 entropyTimer_.cancel(ec);
1603 JLOG(m_journal.error())
1604 <<
"Application: entropyTimer cancel error: " << ec.message();
1610 using namespace std::chrono_literals;
1612 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1614 mValidations.flush();
1616 validatorSites_->stop();
1619 validatorManifests_->save(
1620 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1621 return validators().listed(pubKey);
1624 publisherManifests_->save(
1625 getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1626 return validators().trustedPublisher(pubKey);
1631 m_loadManager->stop();
1632 m_shaMapStore->stop();
1636 grpcServer_->stop();
1637 m_networkOPs->stop();
1638 serverHandler_->stop();
1639 m_ledgerReplayer->stop();
1640 m_inboundTransactions->stop();
1641 m_inboundLedgers->stop();
1642 ledgerCleaner_->stop();
1643 m_nodeStore->stop();
1646 JLOG(m_journal.info()) <<
"Done.";
1652 if (!isTimeToStop.exchange(
true))
1655 JLOG(m_journal.warn()) <<
"Server stopping";
1657 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1659 stoppingCondition_.notify_all();
1664ApplicationImp::checkSigs()
const
1670ApplicationImp::checkSigs(
bool check)
1676ApplicationImp::isStopping()
const
1678 return isTimeToStop.load();
1682ApplicationImp::fdRequired()
const
1689 needed += 2 * overlay_->limit();
1693 needed +=
std::max(5, m_shaMapStore->fdRequired());
1697 for (
auto const& p : serverHandler_->setup().ports)
1707ApplicationImp::startGenesisLedger()
1710 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1715 m_ledgerMaster->storeLedger(genesis);
1718 std::make_shared<Ledger>(*genesis, timeKeeper().closeTime());
1719 next->updateSkipList();
1721 next->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1722 next->read(keylet::fees()),
1723 "ripple::ApplicationImp::startGenesisLedger : valid ledger fees");
1724 next->setImmutable();
1725 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1726 m_ledgerMaster->storeLedger(next);
1727 m_ledgerMaster->switchLCL(next);
1731ApplicationImp::getLastFullLedger()
1733 auto j = journal(
"Ledger");
1743 ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1744 ledger->read(keylet::fees()),
1745 "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
1746 ledger->setImmutable();
1748 if (getLedgerMaster().haveLedger(seq))
1749 ledger->setValidated();
1751 if (ledger->info().hash ==
hash)
1753 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1757 if (
auto stream = j.error())
1759 stream <<
"Failed on ledger";
1761 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1769 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1783 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1790 if (!reader.
parse(ledgerFile, jLedger))
1792 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1799 if (ledger.
get().isMember(
"result"))
1800 ledger = ledger.
get()[
"result"];
1802 if (ledger.
get().isMember(
"ledger"))
1803 ledger = ledger.
get()[
"ledger"];
1806 auto closeTime = timeKeeper().closeTime();
1807 using namespace std::chrono_literals;
1808 auto closeTimeResolution = 30s;
1809 bool closeTimeEstimated =
false;
1812 if (ledger.
get().isMember(
"accountState"))
1814 if (ledger.
get().isMember(jss::ledger_index))
1816 seq = ledger.
get()[jss::ledger_index].asUInt();
1819 if (ledger.
get().isMember(
"close_time"))
1822 using d = tp::duration;
1823 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1825 if (ledger.
get().isMember(
"close_time_resolution"))
1828 closeTimeResolution =
1829 seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1831 if (ledger.
get().isMember(
"close_time_estimated"))
1833 closeTimeEstimated =
1834 ledger.
get()[
"close_time_estimated"].asBool();
1836 if (ledger.
get().isMember(
"total_coins"))
1838 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1839 ledger.
get()[
"total_coins"].asString());
1842 ledger = ledger.
get()[
"accountState"];
1845 if (!ledger.
get().isArrayOrNull())
1847 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1852 std::make_shared<Ledger>(seq, closeTime, *config_, nodeFamily_);
1853 loadLedger->setTotalDrops(totalDrops);
1855 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1861 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1869 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1879 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1887 if (!loadLedger->addSLE(sle))
1889 JLOG(m_journal.fatal())
1890 <<
"Couldn't add serialized ledger: " << uIndex;
1898 loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1899 loadLedger->read(keylet::fees()),
1900 "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1901 loadLedger->setAccepted(
1902 closeTime, closeTimeResolution, !closeTimeEstimated);
1908 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1914ApplicationImp::loadOldLedger(
1926 if (!ledgerID.
empty())
1927 loadLedger = loadLedgerFromFile(ledgerID);
1929 else if (ledgerID.
length() == 64)
1933 if (
hash.parseHex(ledgerID))
1940 auto il = std::make_shared<InboundLedger>(
1944 InboundLedger::Reason::GENERIC,
1947 if (il->checkLocal())
1948 loadLedger = il->getLedger();
1952 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1954 loadLedger = getLastFullLedger();
1973 replayLedger = loadLedger;
1975 JLOG(m_journal.info()) <<
"Loading parent ledger";
1977 loadLedger =
loadByHash(replayLedger->info().parentHash, *
this);
1980 JLOG(m_journal.info())
1981 <<
"Loading parent ledger from node store";
1984 auto il = std::make_shared<InboundLedger>(
1986 replayLedger->info().parentHash,
1988 InboundLedger::Reason::GENERIC,
1992 if (il->checkLocal())
1993 loadLedger = il->getLedger();
1997 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1999 "ripple::ApplicationImp::loadOldLedger : replay ledger "
2005 using namespace std::chrono_literals;
2006 using namespace date;
2008 sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}};
2009 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
2011 JLOG(m_journal.fatal())
2012 <<
"\n\n*** WARNING ***\n"
2013 "You are replaying a ledger from before "
2014 << to_string(ledgerWarnTimePoint)
2016 "This replay will not handle your ledger as it was "
2018 "handled.\nConsider running an earlier version of rippled "
2020 "get the older rules.\n*** CONTINUING ***\n";
2023 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->info().hash
2024 <<
" seq:" << loadLedger->info().seq;
2026 if (loadLedger->info().accountHash.isZero())
2028 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
2030 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2034 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
2036 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
2038 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2043 if (!loadLedger->assertSensible(journal(
"Ledger")))
2045 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
2047 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2052 m_ledgerMaster->setLedgerRangePresent(
2053 loadLedger->info().seq, loadLedger->info().seq);
2055 m_ledgerMaster->switchLCL(loadLedger);
2056 loadLedger->setValidated();
2057 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
2058 openLedger_.emplace(
2059 loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
2066 std::make_unique<LedgerReplay>(loadLedger, replayLedger);
2068 for (
auto const& [_, tx] : replayData->orderedTxns())
2071 auto txID = tx->getTransactionID();
2072 if (trapTxID == txID)
2075 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
2078 auto s = std::make_shared<Serializer>();
2081 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2083 openLedger_->modify(
2090 m_ledgerMaster->takeReplay(std::move(replayData));
2092 if (trapTxID && !trapTxID_)
2094 JLOG(m_journal.fatal())
2095 <<
"Ledger " << replayLedger->info().seq
2096 <<
" does not contain the transaction hash " << *trapTxID;
2103 JLOG(m_journal.fatal())
2104 <<
"While loading specified ledger: " << mn.
what();
2107 catch (boost::bad_lexical_cast&)
2109 JLOG(m_journal.fatal())
2110 <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2120 if (!config().ELB_SUPPORT)
2125 reason =
"Server is shutting down";
2129 if (getOPs().isNeedNetworkLedger())
2131 reason =
"Not synchronized with network yet";
2135 if (getOPs().isAmendmentBlocked())
2137 reason =
"Server version too old";
2141 if (getOPs().isUNLBlocked())
2143 reason =
"No valid validator list available";
2147 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2149 reason =
"Not synchronized with network";
2153 if (!getLedgerMaster().isCaughtUp(reason))
2156 if (getFeeTrack().isLoadedLocal())
2158 reason =
"Too much load";
2168 return logs_->journal(name);
2172ApplicationImp::setMaxDisallowedLedger()
2174 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2176 maxDisallowedLedger_ = *seq;
2178 JLOG(m_journal.trace())
2179 <<
"Max persisted ledger is " << maxDisallowedLedger_;
2196 return std::make_unique<ApplicationImp>(
2197 std::move(config), std::move(logs), std::move(timeKeeper));
2203 for (
auto const& [name, ep] : endpoints)
2205 if (!config.
exists(name))
2208 auto& section = config[name];
2209 auto const optPort = section.get(
"port");
2213 beast::lexicalCast<std::uint16_t>(*optPort);
boost::asio::io_service & get_io_service()
Unserialize a JSON document into a Value.
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
bool isObjectOrNull() const
Value removeMember(const char *key)
Remove and return the named member.
std::string asString() const
Returns the unquoted string value.
A generic endpoint for log messages.
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.
void notify(std::chrono::duration< Rep, Period > const &value) const
Push an event notification.
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.
beast::insight::Event m_event
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
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
OrderBookDB m_orderBookDB
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
std::mutex stoppingMutex_
TimeKeeper & timeKeeper() override
std::optional< PublicKey const > getValidationPublicKey() const override
std::unique_ptr< ValidatorSite > validatorSites_
std::unique_ptr< CollectorManager > m_collectorManager
SHAMapStore & getSHAMapStore() override
InboundLedgers & getInboundLedgers() override
NodeCache m_tempNodeCache
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 initRelationalDatabase()
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.
Routing table for objects identified by hash.
static std::chrono::seconds getDefaultHoldTime()
Manages the lifetime of inbound ledgers.
Manages the acquisition and lifetime of transaction sets.
A pool of threads to perform work.
Check the ledger/transaction databases to make sure they have continuity.
Manages the lifetime of ledger replay tasks.
Manages the current fee schedule.
Manages partitions for logging.
Remembers manifests with the highest sequence number.
Provides server functionality for clients.
A NodeStore::Scheduler which uses the JobQueue.
Persistency layer for NodeObject.
Simple NodeStore Scheduler that just peforms the tasks synchronously.
virtual std::unique_ptr< Database > make_Database(std::size_t burstSize, Scheduler &scheduler, int readThreads, Section const &backendParameters, beast::Journal journal)=0
Construct a NodeStore database.
static Manager & instance()
Returns the instance of the manager singleton.
Represents the open ledger.
Writable ledger view that accumulates state and tx changes.
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.
Manages the set of connected peers.
Keeps track of which ledgers haven't been fully saved.
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)
An endpoint that consumes resources.
Tracks load and resource consumption.
class to create database, launch online delete thread, and related SQLite database
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
Holds a collection of configuration values.
std::size_t size() const
Returns the number of items in the container.
Manages various times used by the server.
Validator keys and manifest as set in configuration file.
std::optional< Keys > keys
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Singleton class that maintains performance counters and optionally writes Json-formatted data to a di...
T hardware_concurrency(T... args)
A namespace for easy access to logging severity values.
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
std::unique_ptr< Manager > make_Manager(beast::insight::Collector::ptr const &collector, beast::Journal journal)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
constexpr auto megabytes(T value) noexcept
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::unique_ptr< LedgerCleaner > make_LedgerCleaner(Application &app, beast::Journal journal)
TxQ::Setup setup_TxQ(Config const &config)
Build a TxQ::Setup object from application configuration.
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
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.
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
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.
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
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 ¶ms, 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.
std::optional< uint256 > getRegisteredFeature(std::string const &name)
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
create_genesis_t const create_genesis
static void fixConfigPorts(Config &config, Endpoints const &endpoints)
std::unique_ptr< AmendmentTable > make_AmendmentTable(Application &app, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
Overlay::Setup setup_Overlay(BasicConfig const &config)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
std::unique_ptr< 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)
static std::string importNodeDatabase()