20#include <xrpld/app/consensus/RCLValidations.h>
21#include <xrpld/app/ledger/InboundLedgers.h>
22#include <xrpld/app/ledger/InboundTransactions.h>
23#include <xrpld/app/ledger/LedgerCleaner.h>
24#include <xrpld/app/ledger/LedgerMaster.h>
25#include <xrpld/app/ledger/LedgerReplayer.h>
26#include <xrpld/app/ledger/LedgerToJson.h>
27#include <xrpld/app/ledger/OpenLedger.h>
28#include <xrpld/app/ledger/OrderBookDB.h>
29#include <xrpld/app/ledger/PendingSaves.h>
30#include <xrpld/app/ledger/TransactionMaster.h>
31#include <xrpld/app/main/Application.h>
32#include <xrpld/app/main/BasicApp.h>
33#include <xrpld/app/main/DBInit.h>
34#include <xrpld/app/main/GRPCServer.h>
35#include <xrpld/app/main/LoadManager.h>
36#include <xrpld/app/main/NodeIdentity.h>
37#include <xrpld/app/main/NodeStoreScheduler.h>
38#include <xrpld/app/misc/AmendmentTable.h>
39#include <xrpld/app/misc/HashRouter.h>
40#include <xrpld/app/misc/LoadFeeTrack.h>
41#include <xrpld/app/misc/NetworkOPs.h>
42#include <xrpld/app/misc/SHAMapStore.h>
43#include <xrpld/app/misc/TxQ.h>
44#include <xrpld/app/misc/ValidatorKeys.h>
45#include <xrpld/app/misc/ValidatorSite.h>
46#include <xrpld/app/paths/PathRequests.h>
47#include <xrpld/app/rdb/RelationalDatabase.h>
48#include <xrpld/app/rdb/Wallet.h>
49#include <xrpld/app/tx/apply.h>
50#include <xrpld/core/DatabaseCon.h>
51#include <xrpld/nodestore/DummyScheduler.h>
52#include <xrpld/overlay/Cluster.h>
53#include <xrpld/overlay/PeerReservationTable.h>
54#include <xrpld/overlay/PeerSet.h>
55#include <xrpld/overlay/make_Overlay.h>
56#include <xrpld/perflog/PerfLog.h>
57#include <xrpld/rpc/detail/RPCHelpers.h>
58#include <xrpld/shamap/NodeFamily.h>
59#include <xrpl/basics/ByteUtilities.h>
60#include <xrpl/basics/ResolverAsio.h>
61#include <xrpl/basics/random.h>
62#include <xrpl/beast/asio/io_latency_probe.h>
63#include <xrpl/beast/core/LexicalCast.h>
64#include <xrpl/crypto/csprng.h>
65#include <xrpl/json/json_reader.h>
66#include <xrpl/protocol/BuildInfo.h>
67#include <xrpl/protocol/Feature.h>
68#include <xrpl/protocol/Protocol.h>
69#include <xrpl/protocol/STParsedJSON.h>
70#include <xrpl/resource/Fees.h>
72#include <boost/algorithm/string/predicate.hpp>
73#include <boost/asio/steady_timer.hpp>
74#include <boost/system/error_code.hpp>
109 boost::asio::io_service& ios)
123 template <
class Duration>
128 auto const lastSample = ceil<milliseconds>(elapsed);
132 if (lastSample >= 10ms)
134 if (lastSample >= 500ms)
137 <<
"io_service latency = " << lastSample.count();
243#if RIPPLE_SINGLE_IO_SERVICE_THREAD
291 config_->section(SECTION_INSIGHT),
292 logs_->journal(
"Collector")))
318 logs_->journal(
"JobQueue"),
327 logs_->journal(
"SHAMapStore")))
334 logs_->journal(
"TaggedCache"))
341 logs_->journal(
"CachedSLEs"))
347 logs_->journal(
"Resource")))
358 logs_->journal(
"PathRequest"),
365 logs_->journal(
"LedgerMaster")))
382 gotTXSet(set, fromAcquire);
395 logs_->journal(
"TaggedCache"))
407 logs_->journal(
"NetworkOPs"),
410 ,
cluster_(std::make_unique<Cluster>(
logs_->journal(
"Overlay")))
413 logs_->journal(
"PeerReservationTable")))
416 std::make_unique<ManifestCache>(
logs_->journal(
"ManifestCache")))
419 std::make_unique<ManifestCache>(
logs_->journal(
"ManifestCache")))
425 config_->legacy(
"database_path"),
426 logs_->journal(
"ValidatorList"),
440 std::make_unique<LoadFeeTrack>(
logs_->journal(
"LoadManager")))
450 logs_->journal(
"Validations"))
470 logs_->journal(
"Application"),
500 setup(boost::program_options::variables_map
const& cmdline)
override;
502 start(
bool withTimers)
override;
567 "Accessing Application::nodeIdentity() before it is initialized.");
590 "ripple::ApplicationImp::getServerHandler : non-null server "
595 boost::asio::io_service&
798 overlay_,
"ripple::ApplicationImp::overlay : non-null overlay");
807 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
816 "ripple::ApplicationImp::getRelationalDatabase : non-null "
817 "relational database");
826 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
843 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
853 setup.useGlobalPragma =
false;
860 <<
"Failed to initialize SQL databases: " << e.
what();
872 auto j =
logs_->journal(
"NodeObject");
883 JLOG(j.warn()) <<
"Starting node import from '" << source->getName()
887 auto const start = steady_clock::now();
892 duration_cast<seconds>(steady_clock::now() -
start);
893 JLOG(j.warn()) <<
"Node import from '" << source->getName()
894 <<
"' took " << elapsed.count() <<
" seconds.";
917 [
this](boost::system::error_code
const& e) {
918 if (e.value() == boost::system::errc::success)
921 jtSWEEP,
"sweep", [this]() { doSweep(); });
924 if (e.value() != boost::system::errc::success &&
925 e.value() != boost::asio::error::operation_aborted)
928 JLOG(m_journal.error())
929 <<
"Sweep timer got error '" << e.message()
930 <<
"'. Restarting timer.";
939 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
947 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
948 [
this](boost::system::error_code
const& e) {
949 if (e.value() == boost::system::errc::success)
951 crypto_prng().mix_entropy();
955 if (e.value() != boost::system::errc::success &&
956 e.value() != boost::asio::error::operation_aborted)
959 JLOG(m_journal.error())
960 <<
"Entropy timer got error '" << e.message()
961 <<
"'. Restarting timer.";
966 using namespace std::chrono_literals;
967 entropyTimer_.expires_from_now(5min);
968 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
975 if (!config_->standalone() &&
976 !getRelationalDatabase().transactionDbHasSpace(*config_))
987 nodeFamily_.getFullBelowCache();
990 nodeFamily_.getTreeNodeCache();
992 std::size_t const oldFullBelowSize = fullBelowCache->size();
993 std::size_t const oldTreeNodeSize = treeNodeCache->size();
997 JLOG(m_journal.debug())
998 <<
"NodeFamily::FullBelowCache sweep. Size before: "
1000 <<
"; size after: " << fullBelowCache->size();
1002 JLOG(m_journal.debug())
1003 <<
"NodeFamily::TreeNodeCache sweep. Size before: "
1004 << oldTreeNodeSize <<
"; size after: " << treeNodeCache->size();
1008 getMasterTransaction().getCache();
1012 getMasterTransaction().sweep();
1014 JLOG(m_journal.debug())
1015 <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
1016 <<
"; size after: " << masterTxCache.
size();
1020 getNodeStore().sweep();
1024 getLedgerMaster().getFetchPackCacheSize();
1026 getLedgerMaster().sweep();
1028 JLOG(m_journal.debug())
1029 <<
"LedgerMaster sweep. Size before: "
1030 << oldLedgerMasterCacheSize <<
"; size after: "
1031 << getLedgerMaster().getFetchPackCacheSize();
1035 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1037 getTempNodeCache().sweep();
1039 JLOG(m_journal.debug())
1040 <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1041 <<
"; size after: " << getTempNodeCache().size();
1045 getValidations().sizeOfCurrentCache();
1047 getValidations().sizeOfSeqEnforcersCache();
1049 getValidations().sizeOfByLedgerCache();
1051 getValidations().sizeOfBySequenceCache();
1053 getValidations().expire(m_journal);
1055 JLOG(m_journal.debug())
1056 <<
"Validations Current expire. Size before: "
1057 << oldCurrentCacheSize
1058 <<
"; size after: " << getValidations().sizeOfCurrentCache();
1060 JLOG(m_journal.debug())
1061 <<
"Validations SeqEnforcer expire. Size before: "
1062 << oldSizeSeqEnforcesSize <<
"; size after: "
1063 << getValidations().sizeOfSeqEnforcersCache();
1065 JLOG(m_journal.debug())
1066 <<
"Validations ByLedger expire. Size before: "
1068 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1070 JLOG(m_journal.debug())
1071 <<
"Validations BySequence expire. Size before: "
1072 << oldBySequenceSize
1073 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1077 getInboundLedgers().cacheSize();
1079 getInboundLedgers().sweep();
1081 JLOG(m_journal.debug())
1082 <<
"InboundLedgers sweep. Size before: "
1083 << oldInboundLedgersSize
1084 <<
"; size after: " << getInboundLedgers().cacheSize();
1087 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1088 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1089 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1091 getLedgerReplayer().sweep();
1093 JLOG(m_journal.debug())
1094 <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1095 <<
"; size after: " << getLedgerReplayer().tasksSize();
1097 JLOG(m_journal.debug())
1098 <<
"LedgerReplayer deltas sweep. Size before: "
1100 <<
"; size after: " << getLedgerReplayer().deltasSize();
1102 JLOG(m_journal.debug())
1103 <<
"LedgerReplayer skipLists sweep. Size before: "
1105 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1109 m_acceptedLedgerCache.size();
1111 m_acceptedLedgerCache.sweep();
1113 JLOG(m_journal.debug())
1114 <<
"AcceptedLedgerCache sweep. Size before: "
1115 << oldAcceptedLedgerSize
1116 <<
"; size after: " << m_acceptedLedgerCache.size();
1119 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1121 cachedSLEs_.sweep();
1123 JLOG(m_journal.debug())
1124 <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1125 <<
"; size after: " << cachedSLEs_.size();
1135 return maxDisallowedLedger_;
1150 startGenesisLedger();
1153 getLastFullLedger();
1166 setMaxDisallowedLedger();
1173ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1183 m_signals.add(SIGINT);
1184 m_signals.add(SIGTERM);
1185 m_signals.async_wait(
1186 [
this](boost::system::error_code
const& ec,
int signum) {
1188 if (ec == boost::asio::error::operation_aborted)
1191 JLOG(m_journal.info()) <<
"Received signal " << signum;
1193 if (signum == SIGTERM || signum == SIGINT)
1197 auto debug_log = config_->getDebugLogFile();
1199 if (!debug_log.empty())
1204 if (!logs_->open(debug_log))
1205 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1208 if (logs_->threshold() > kDebug)
1209 logs_->threshold(kDebug);
1212 JLOG(m_journal.info()) <<
"Process starting: "
1213 << BuildInfo::getFullVersionString()
1214 <<
", Instance Cookie: " << instanceCookie_;
1216 if (numberOfThreads(*config_) < 2)
1218 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1219 "system configuration.";
1223 logs_->silent(config_->silent());
1225 if (!initRelationalDatabase() || !initNodeStore())
1228 if (!peerReservations_->load(getWalletDB()))
1230 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1234 if (validatorKeys_.keys)
1235 setMaxDisallowedLedger();
1239 auto const supported = []() {
1240 auto const& amendments = detail::supportedAmendments();
1242 supported.reserve(amendments.size());
1243 for (
auto const& [a, vote] : amendments)
1247 f,
"ripple::ApplicationImp::setup : registered feature");
1249 supported.emplace_back(a, *f, vote);
1253 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1255 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1259 config().AMENDMENT_MAJORITY_TIME,
1263 logs_->journal(
"Amendments"));
1266 Pathfinder::initPathTable();
1268 auto const startUp = config_->START_UP;
1269 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1270 if (startUp == Config::FRESH)
1272 JLOG(m_journal.info()) <<
"Starting new Ledger";
1274 startGenesisLedger();
1277 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1278 startUp == Config::REPLAY)
1280 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1283 config_->START_LEDGER,
1284 startUp == Config::REPLAY,
1285 startUp == Config::LOAD_FILE,
1286 config_->TRAP_TX_HASH))
1288 JLOG(m_journal.error())
1289 <<
"The specified ledger could not be loaded.";
1290 if (config_->FAST_LOAD)
1294 startGenesisLedger();
1302 else if (startUp == Config::NETWORK)
1306 if (!config_->standalone())
1307 m_networkOPs->setNeedNetworkLedger();
1309 startGenesisLedger();
1313 startGenesisLedger();
1316 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1318 m_ledgerMaster->setLedgerRangePresent(
1319 forcedRange->first, forcedRange->second);
1322 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1326 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1328 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1333 if (validatorKeys_.configInvalid())
1336 if (!validatorManifests_->load(
1338 "ValidatorManifests",
1339 validatorKeys_.manifest,
1340 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1342 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1346 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1355 if (validatorKeys_.keys)
1356 localSigningKey = validatorKeys_.keys->publicKey;
1359 if (!validators_->load(
1361 config().section(SECTION_VALIDATORS).values(),
1362 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1363 config().VALIDATOR_LIST_THRESHOLD))
1365 JLOG(m_journal.fatal())
1366 <<
"Invalid entry in validator configuration.";
1371 if (!validatorSites_->load(
1372 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1374 JLOG(m_journal.fatal())
1375 <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1380 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1401 m_collectorManager->collector());
1405 if (!m_networkOPs->beginConsensus(
1406 m_ledgerMaster->getClosedLedger()->info().hash, {}))
1408 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1418 serverHandler_->setup(setup, m_journal);
1423 if (
auto stream = m_journal.fatal())
1425 stream <<
"Unable to setup server handler";
1427 stream <<
": " << e.
what();
1434 if (!config_->standalone())
1438 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1440 JLOG(m_journal.warn())
1441 <<
"No outbound peer connections will be made";
1446 m_networkOPs->setStateTimer();
1450 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1452 m_networkOPs->setStandAlone();
1455 if (config_->canSign())
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.";
1477 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1482 if (!jrReader.
parse(cmd, jvCommand))
1484 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in ["
1485 << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1488 if (!config_->quiet())
1490 JLOG(m_journal.fatal())
1491 <<
"Startup RPC: " << jvCommand <<
std::endl;
1497 {journal(
"RPCHandler"),
1506 RPC::apiMaximumSupportedVersion},
1510 RPC::doCommand(context, jvResult);
1512 if (!config_->quiet())
1514 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1518 validatorSites_->start();
1524ApplicationImp::start(
bool withTimers)
1526 JLOG(m_journal.info()) <<
"Application starting. Version is "
1527 << BuildInfo::getVersionString();
1535 m_io_latency_sampler.start();
1536 m_resolver->start();
1537 m_loadManager->start();
1538 m_shaMapStore->start();
1542 if (grpcServer_->start())
1544 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1546 ledgerCleaner_->start();
1551ApplicationImp::run()
1553 if (!config_->standalone())
1559 getLoadManager().activateDeadlockDetector();
1564 stoppingCondition_.wait(lk, [
this] {
return isTimeToStop.load(); });
1567 JLOG(m_journal.debug()) <<
"Application stopping";
1569 m_io_latency_sampler.cancel_async();
1577 m_io_latency_sampler.cancel();
1579 m_resolver->stop_async();
1587 boost::system::error_code ec;
1588 sweepTimer_.cancel(ec);
1591 JLOG(m_journal.error())
1592 <<
"Application: sweepTimer cancel error: " << ec.message();
1596 entropyTimer_.cancel(ec);
1599 JLOG(m_journal.error())
1600 <<
"Application: entropyTimer cancel error: " << ec.message();
1606 using namespace std::chrono_literals;
1608 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1610 mValidations.flush();
1612 validatorSites_->stop();
1615 validatorManifests_->save(
1616 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1617 return validators().listed(pubKey);
1620 publisherManifests_->save(
1621 getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1622 return validators().trustedPublisher(pubKey);
1627 m_loadManager->stop();
1628 m_shaMapStore->stop();
1632 grpcServer_->stop();
1633 m_networkOPs->stop();
1634 serverHandler_->stop();
1635 m_ledgerReplayer->stop();
1636 m_inboundTransactions->stop();
1637 m_inboundLedgers->stop();
1638 ledgerCleaner_->stop();
1639 m_nodeStore->stop();
1642 JLOG(m_journal.info()) <<
"Done.";
1648 if (!isTimeToStop.exchange(
true))
1651 JLOG(m_journal.warn()) <<
"Server stopping";
1653 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1655 stoppingCondition_.notify_all();
1660ApplicationImp::checkSigs()
const
1666ApplicationImp::checkSigs(
bool check)
1672ApplicationImp::isStopping()
const
1674 return isTimeToStop.load();
1678ApplicationImp::fdRequired()
const
1685 needed += 2 * overlay_->limit();
1689 needed +=
std::max(5, m_shaMapStore->fdRequired());
1693 for (
auto const& p : serverHandler_->setup().ports)
1703ApplicationImp::startGenesisLedger()
1706 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1711 m_ledgerMaster->storeLedger(genesis);
1714 std::make_shared<Ledger>(*genesis, timeKeeper().closeTime());
1715 next->updateSkipList();
1717 next->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1718 next->read(keylet::fees()),
1719 "ripple::ApplicationImp::startGenesisLedger : valid ledger fees");
1720 next->setImmutable();
1721 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1722 m_ledgerMaster->storeLedger(next);
1723 m_ledgerMaster->switchLCL(next);
1727ApplicationImp::getLastFullLedger()
1729 auto j = journal(
"Ledger");
1739 ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1740 ledger->read(keylet::fees()),
1741 "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
1742 ledger->setImmutable();
1744 if (getLedgerMaster().haveLedger(seq))
1745 ledger->setValidated();
1747 if (ledger->info().hash ==
hash)
1749 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1753 if (
auto stream = j.error())
1755 stream <<
"Failed on ledger";
1757 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1765 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1779 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1786 if (!reader.
parse(ledgerFile, jLedger))
1788 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1795 if (ledger.
get().isMember(
"result"))
1796 ledger = ledger.
get()[
"result"];
1798 if (ledger.
get().isMember(
"ledger"))
1799 ledger = ledger.
get()[
"ledger"];
1802 auto closeTime = timeKeeper().closeTime();
1803 using namespace std::chrono_literals;
1804 auto closeTimeResolution = 30s;
1805 bool closeTimeEstimated =
false;
1808 if (ledger.
get().isMember(
"accountState"))
1810 if (ledger.
get().isMember(jss::ledger_index))
1812 seq = ledger.
get()[jss::ledger_index].asUInt();
1815 if (ledger.
get().isMember(
"close_time"))
1818 using d = tp::duration;
1819 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1821 if (ledger.
get().isMember(
"close_time_resolution"))
1824 closeTimeResolution =
1825 seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1827 if (ledger.
get().isMember(
"close_time_estimated"))
1829 closeTimeEstimated =
1830 ledger.
get()[
"close_time_estimated"].asBool();
1832 if (ledger.
get().isMember(
"total_coins"))
1834 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1835 ledger.
get()[
"total_coins"].asString());
1838 ledger = ledger.
get()[
"accountState"];
1841 if (!ledger.
get().isArrayOrNull())
1843 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1848 std::make_shared<Ledger>(seq, closeTime, *config_, nodeFamily_);
1849 loadLedger->setTotalDrops(totalDrops);
1851 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1857 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1865 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1875 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1883 if (!loadLedger->addSLE(sle))
1885 JLOG(m_journal.fatal())
1886 <<
"Couldn't add serialized ledger: " << uIndex;
1894 loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1895 loadLedger->read(keylet::fees()),
1896 "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1897 loadLedger->setAccepted(
1898 closeTime, closeTimeResolution, !closeTimeEstimated);
1904 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1910ApplicationImp::loadOldLedger(
1922 if (!ledgerID.
empty())
1923 loadLedger = loadLedgerFromFile(ledgerID);
1925 else if (ledgerID.
length() == 64)
1929 if (
hash.parseHex(ledgerID))
1936 auto il = std::make_shared<InboundLedger>(
1940 InboundLedger::Reason::GENERIC,
1943 if (il->checkLocal())
1944 loadLedger = il->getLedger();
1948 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1950 loadLedger = getLastFullLedger();
1969 replayLedger = loadLedger;
1971 JLOG(m_journal.info()) <<
"Loading parent ledger";
1973 loadLedger =
loadByHash(replayLedger->info().parentHash, *
this);
1976 JLOG(m_journal.info())
1977 <<
"Loading parent ledger from node store";
1980 auto il = std::make_shared<InboundLedger>(
1982 replayLedger->info().parentHash,
1984 InboundLedger::Reason::GENERIC,
1988 if (il->checkLocal())
1989 loadLedger = il->getLedger();
1993 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1995 "ripple::ApplicationImp::loadOldLedger : replay ledger "
2001 using namespace std::chrono_literals;
2002 using namespace date;
2004 sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}};
2005 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
2007 JLOG(m_journal.fatal())
2008 <<
"\n\n*** WARNING ***\n"
2009 "You are replaying a ledger from before "
2010 << to_string(ledgerWarnTimePoint)
2012 "This replay will not handle your ledger as it was "
2014 "handled.\nConsider running an earlier version of rippled "
2016 "get the older rules.\n*** CONTINUING ***\n";
2019 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->info().hash
2020 <<
" seq:" << loadLedger->info().seq;
2022 if (loadLedger->info().accountHash.isZero())
2024 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
2026 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2030 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
2032 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
2034 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2039 if (!loadLedger->assertSensible(journal(
"Ledger")))
2041 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
2043 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2048 m_ledgerMaster->setLedgerRangePresent(
2049 loadLedger->info().seq, loadLedger->info().seq);
2051 m_ledgerMaster->switchLCL(loadLedger);
2052 loadLedger->setValidated();
2053 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
2054 openLedger_.emplace(
2055 loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
2062 std::make_unique<LedgerReplay>(loadLedger, replayLedger);
2064 for (
auto const& [_, tx] : replayData->orderedTxns())
2067 auto txID = tx->getTransactionID();
2068 if (trapTxID == txID)
2071 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
2074 auto s = std::make_shared<Serializer>();
2077 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2079 openLedger_->modify(
2086 m_ledgerMaster->takeReplay(std::move(replayData));
2088 if (trapTxID && !trapTxID_)
2090 JLOG(m_journal.fatal())
2091 <<
"Ledger " << replayLedger->info().seq
2092 <<
" does not contain the transaction hash " << *trapTxID;
2099 JLOG(m_journal.fatal())
2100 <<
"While loading specified ledger: " << mn.
what();
2103 catch (boost::bad_lexical_cast&)
2105 JLOG(m_journal.fatal())
2106 <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2116 if (!config().ELB_SUPPORT)
2121 reason =
"Server is shutting down";
2125 if (getOPs().isNeedNetworkLedger())
2127 reason =
"Not synchronized with network yet";
2131 if (getOPs().isAmendmentBlocked())
2133 reason =
"Server version too old";
2137 if (getOPs().isUNLBlocked())
2139 reason =
"No valid validator list available";
2143 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2145 reason =
"Not synchronized with network";
2149 if (!getLedgerMaster().isCaughtUp(reason))
2152 if (getFeeTrack().isLoadedLocal())
2154 reason =
"Too much load";
2164 return logs_->journal(name);
2168ApplicationImp::setMaxDisallowedLedger()
2170 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2172 maxDisallowedLedger_ = *seq;
2174 JLOG(m_journal.trace())
2175 <<
"Max persisted ledger is " << maxDisallowedLedger_;
2192 return std::make_unique<ApplicationImp>(
2193 std::move(config), std::move(logs), std::move(timeKeeper));
2199 for (
auto const& [name, ep] : endpoints)
2201 if (!config.
exists(name))
2204 auto& section = config[name];
2205 auto const optPort = section.get(
"port");
2209 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()