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>
110 boost::asio::io_service& ios)
124 template <
class Duration>
129 auto const lastSample = ceil<milliseconds>(elapsed);
133 if (lastSample >= 10ms)
135 if (lastSample >= 500ms)
138 <<
"io_service latency = " << lastSample.count();
244#if RIPPLE_SINGLE_IO_SERVICE_THREAD
292 config_->section(SECTION_INSIGHT),
293 logs_->journal(
"Collector")))
319 logs_->journal(
"JobQueue"),
328 logs_->journal(
"SHAMapStore")))
335 logs_->journal(
"TaggedCache"))
342 logs_->journal(
"CachedSLEs"))
348 logs_->journal(
"Resource")))
359 logs_->journal(
"PathRequest"),
366 logs_->journal(
"LedgerMaster")))
383 gotTXSet(set, fromAcquire);
396 logs_->journal(
"TaggedCache"))
408 logs_->journal(
"NetworkOPs"),
411 ,
cluster_(std::make_unique<Cluster>(
logs_->journal(
"Overlay")))
414 logs_->journal(
"PeerReservationTable")))
417 std::make_unique<ManifestCache>(
logs_->journal(
"ManifestCache")))
420 std::make_unique<ManifestCache>(
logs_->journal(
"ManifestCache")))
426 config_->legacy(
"database_path"),
427 logs_->journal(
"ValidatorList"),
441 std::make_unique<LoadFeeTrack>(
logs_->journal(
"LoadManager")))
451 logs_->journal(
"Validations"))
471 logs_->journal(
"Application"),
501 setup(boost::program_options::variables_map
const& cmdline)
override;
503 start(
bool withTimers)
override;
568 "Accessing Application::nodeIdentity() before it is initialized.");
591 "ripple::ApplicationImp::getServerHandler : non-null server "
596 boost::asio::io_service&
799 overlay_,
"ripple::ApplicationImp::overlay : non-null overlay");
808 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
817 "ripple::ApplicationImp::getRelationalDatabase : non-null "
818 "relational database");
827 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
844 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
854 setup.useGlobalPragma =
false;
861 <<
"Failed to initialize SQL databases: " << e.
what();
873 auto j =
logs_->journal(
"NodeObject");
884 JLOG(j.warn()) <<
"Starting node import from '" << source->getName()
888 auto const start = steady_clock::now();
893 duration_cast<seconds>(steady_clock::now() -
start);
894 JLOG(j.warn()) <<
"Node import from '" << source->getName()
895 <<
"' took " << elapsed.count() <<
" seconds.";
918 [
this](boost::system::error_code
const& e) {
919 if (e.value() == boost::system::errc::success)
922 jtSWEEP,
"sweep", [this]() { doSweep(); });
925 if (e.value() != boost::system::errc::success &&
926 e.value() != boost::asio::error::operation_aborted)
929 JLOG(m_journal.error())
930 <<
"Sweep timer got error '" << e.message()
931 <<
"'. Restarting timer.";
940 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
948 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
949 [
this](boost::system::error_code
const& e) {
950 if (e.value() == boost::system::errc::success)
952 crypto_prng().mix_entropy();
956 if (e.value() != boost::system::errc::success &&
957 e.value() != boost::asio::error::operation_aborted)
960 JLOG(m_journal.error())
961 <<
"Entropy timer got error '" << e.message()
962 <<
"'. Restarting timer.";
967 using namespace std::chrono_literals;
968 entropyTimer_.expires_from_now(5min);
969 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
976 if (!config_->standalone() &&
977 !getRelationalDatabase().transactionDbHasSpace(*config_))
988 nodeFamily_.getFullBelowCache();
991 nodeFamily_.getTreeNodeCache();
993 std::size_t const oldFullBelowSize = fullBelowCache->size();
994 std::size_t const oldTreeNodeSize = treeNodeCache->size();
998 JLOG(m_journal.debug())
999 <<
"NodeFamily::FullBelowCache sweep. Size before: "
1001 <<
"; size after: " << fullBelowCache->size();
1003 JLOG(m_journal.debug())
1004 <<
"NodeFamily::TreeNodeCache sweep. Size before: "
1005 << oldTreeNodeSize <<
"; size after: " << treeNodeCache->size();
1009 getMasterTransaction().getCache();
1013 getMasterTransaction().sweep();
1015 JLOG(m_journal.debug())
1016 <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
1017 <<
"; size after: " << masterTxCache.
size();
1021 getNodeStore().sweep();
1025 getLedgerMaster().getFetchPackCacheSize();
1027 getLedgerMaster().sweep();
1029 JLOG(m_journal.debug())
1030 <<
"LedgerMaster sweep. Size before: "
1031 << oldLedgerMasterCacheSize <<
"; size after: "
1032 << getLedgerMaster().getFetchPackCacheSize();
1036 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1038 getTempNodeCache().sweep();
1040 JLOG(m_journal.debug())
1041 <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1042 <<
"; size after: " << getTempNodeCache().size();
1046 getValidations().sizeOfCurrentCache();
1048 getValidations().sizeOfSeqEnforcersCache();
1050 getValidations().sizeOfByLedgerCache();
1052 getValidations().sizeOfBySequenceCache();
1054 getValidations().expire(m_journal);
1056 JLOG(m_journal.debug())
1057 <<
"Validations Current expire. Size before: "
1058 << oldCurrentCacheSize
1059 <<
"; size after: " << getValidations().sizeOfCurrentCache();
1061 JLOG(m_journal.debug())
1062 <<
"Validations SeqEnforcer expire. Size before: "
1063 << oldSizeSeqEnforcesSize <<
"; size after: "
1064 << getValidations().sizeOfSeqEnforcersCache();
1066 JLOG(m_journal.debug())
1067 <<
"Validations ByLedger expire. Size before: "
1069 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1071 JLOG(m_journal.debug())
1072 <<
"Validations BySequence expire. Size before: "
1073 << oldBySequenceSize
1074 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1078 getInboundLedgers().cacheSize();
1080 getInboundLedgers().sweep();
1082 JLOG(m_journal.debug())
1083 <<
"InboundLedgers sweep. Size before: "
1084 << oldInboundLedgersSize
1085 <<
"; size after: " << getInboundLedgers().cacheSize();
1088 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1089 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1090 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1092 getLedgerReplayer().sweep();
1094 JLOG(m_journal.debug())
1095 <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1096 <<
"; size after: " << getLedgerReplayer().tasksSize();
1098 JLOG(m_journal.debug())
1099 <<
"LedgerReplayer deltas sweep. Size before: "
1101 <<
"; size after: " << getLedgerReplayer().deltasSize();
1103 JLOG(m_journal.debug())
1104 <<
"LedgerReplayer skipLists sweep. Size before: "
1106 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1110 m_acceptedLedgerCache.size();
1112 m_acceptedLedgerCache.sweep();
1114 JLOG(m_journal.debug())
1115 <<
"AcceptedLedgerCache sweep. Size before: "
1116 << oldAcceptedLedgerSize
1117 <<
"; size after: " << m_acceptedLedgerCache.size();
1120 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1122 cachedSLEs_.sweep();
1124 JLOG(m_journal.debug())
1125 <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1126 <<
"; size after: " << cachedSLEs_.size();
1136 return maxDisallowedLedger_;
1151 startGenesisLedger();
1154 getLastFullLedger();
1167 setMaxDisallowedLedger();
1174ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
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) {
1189 if (ec == boost::asio::error::operation_aborted)
1192 JLOG(m_journal.info()) <<
"Received signal " << signum;
1194 if (signum == SIGTERM || signum == SIGINT)
1198 auto debug_log = config_->getDebugLogFile();
1200 if (!debug_log.empty())
1205 if (!logs_->open(debug_log))
1206 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1209 if (logs_->threshold() > kDebug)
1210 logs_->threshold(kDebug);
1213 JLOG(m_journal.info()) <<
"Process starting: "
1214 << BuildInfo::getFullVersionString()
1215 <<
", Instance Cookie: " << instanceCookie_;
1217 if (numberOfThreads(*config_) < 2)
1219 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1220 "system configuration.";
1224 logs_->silent(config_->silent());
1226 if (!initRelationalDatabase() || !initNodeStore())
1229 if (!peerReservations_->load(getWalletDB()))
1231 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1235 if (validatorKeys_.keys)
1236 setMaxDisallowedLedger();
1240 auto const supported = []() {
1241 auto const& amendments = detail::supportedAmendments();
1243 supported.reserve(amendments.size());
1244 for (
auto const& [a, vote] : amendments)
1248 f,
"ripple::ApplicationImp::setup : registered feature");
1250 supported.emplace_back(a, *f, vote);
1254 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1256 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1260 config().AMENDMENT_MAJORITY_TIME,
1264 logs_->journal(
"Amendments"));
1267 Pathfinder::initPathTable();
1269 auto const startUp = config_->START_UP;
1270 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1271 if (startUp == Config::FRESH)
1273 JLOG(m_journal.info()) <<
"Starting new Ledger";
1275 startGenesisLedger();
1278 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1279 startUp == Config::REPLAY)
1281 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1284 config_->START_LEDGER,
1285 startUp == Config::REPLAY,
1286 startUp == Config::LOAD_FILE,
1287 config_->TRAP_TX_HASH))
1289 JLOG(m_journal.error())
1290 <<
"The specified ledger could not be loaded.";
1291 if (config_->FAST_LOAD)
1295 startGenesisLedger();
1303 else if (startUp == Config::NETWORK)
1307 if (!config_->standalone())
1308 m_networkOPs->setNeedNetworkLedger();
1310 startGenesisLedger();
1314 startGenesisLedger();
1317 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1319 m_ledgerMaster->setLedgerRangePresent(
1320 forcedRange->first, forcedRange->second);
1323 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1327 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1329 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1334 if (validatorKeys_.configInvalid())
1337 if (!validatorManifests_->load(
1339 "ValidatorManifests",
1340 validatorKeys_.manifest,
1341 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1343 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1347 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1356 if (validatorKeys_.keys)
1357 localSigningKey = validatorKeys_.keys->publicKey;
1360 if (!validators_->load(
1362 config().section(SECTION_VALIDATORS).values(),
1363 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1364 config().VALIDATOR_LIST_THRESHOLD))
1366 JLOG(m_journal.fatal())
1367 <<
"Invalid entry in validator configuration.";
1372 if (!validatorSites_->load(
1373 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1375 JLOG(m_journal.fatal())
1376 <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1381 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1402 m_collectorManager->collector());
1406 if (!m_networkOPs->beginConsensus(
1407 m_ledgerMaster->getClosedLedger()->info().hash))
1409 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1419 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();
1541 grpcServer_->start();
1542 ledgerCleaner_->start();
1547ApplicationImp::run()
1549 if (!config_->standalone())
1555 getLoadManager().activateDeadlockDetector();
1560 stoppingCondition_.wait(lk, [
this] {
return isTimeToStop.load(); });
1563 JLOG(m_journal.debug()) <<
"Application stopping";
1565 m_io_latency_sampler.cancel_async();
1573 m_io_latency_sampler.cancel();
1575 m_resolver->stop_async();
1583 boost::system::error_code ec;
1584 sweepTimer_.cancel(ec);
1587 JLOG(m_journal.error())
1588 <<
"Application: sweepTimer cancel error: " << ec.message();
1592 entropyTimer_.cancel(ec);
1595 JLOG(m_journal.error())
1596 <<
"Application: entropyTimer cancel error: " << ec.message();
1602 using namespace std::chrono_literals;
1604 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1606 mValidations.flush();
1608 validatorSites_->stop();
1611 validatorManifests_->save(
1612 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1613 return validators().listed(pubKey);
1616 publisherManifests_->save(
1617 getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1618 return validators().trustedPublisher(pubKey);
1623 m_loadManager->stop();
1624 m_shaMapStore->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();
1638 JLOG(m_journal.info()) <<
"Done.";
1644 if (!isTimeToStop.exchange(
true))
1647 JLOG(m_journal.warn()) <<
"Server stopping";
1649 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1651 stoppingCondition_.notify_all();
1656ApplicationImp::checkSigs()
const
1662ApplicationImp::checkSigs(
bool check)
1668ApplicationImp::isStopping()
const
1670 return isTimeToStop.load();
1674ApplicationImp::fdRequired()
const
1681 needed += 2 * overlay_->limit();
1685 needed +=
std::max(5, m_shaMapStore->fdRequired());
1689 for (
auto const& p : serverHandler_->setup().ports)
1699ApplicationImp::startGenesisLedger()
1702 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1707 m_ledgerMaster->storeLedger(genesis);
1710 std::make_shared<Ledger>(*genesis, timeKeeper().closeTime());
1711 next->updateSkipList();
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);
1723ApplicationImp::getLastFullLedger()
1725 auto j = journal(
"Ledger");
1735 ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1736 ledger->read(keylet::fees()),
1737 "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
1738 ledger->setImmutable();
1740 if (getLedgerMaster().haveLedger(seq))
1741 ledger->setValidated();
1743 if (ledger->info().hash ==
hash)
1745 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1749 if (
auto stream = j.error())
1751 stream <<
"Failed on ledger";
1753 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1761 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1775 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1782 if (!reader.
parse(ledgerFile, jLedger))
1784 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1791 if (ledger.
get().isMember(
"result"))
1792 ledger = ledger.
get()[
"result"];
1794 if (ledger.
get().isMember(
"ledger"))
1795 ledger = ledger.
get()[
"ledger"];
1798 auto closeTime = timeKeeper().closeTime();
1799 using namespace std::chrono_literals;
1800 auto closeTimeResolution = 30s;
1801 bool closeTimeEstimated =
false;
1804 if (ledger.
get().isMember(
"accountState"))
1806 if (ledger.
get().isMember(jss::ledger_index))
1808 seq = ledger.
get()[jss::ledger_index].asUInt();
1811 if (ledger.
get().isMember(
"close_time"))
1814 using d = tp::duration;
1815 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1817 if (ledger.
get().isMember(
"close_time_resolution"))
1820 closeTimeResolution =
1821 seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1823 if (ledger.
get().isMember(
"close_time_estimated"))
1825 closeTimeEstimated =
1826 ledger.
get()[
"close_time_estimated"].asBool();
1828 if (ledger.
get().isMember(
"total_coins"))
1830 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1831 ledger.
get()[
"total_coins"].asString());
1834 ledger = ledger.
get()[
"accountState"];
1837 if (!ledger.
get().isArrayOrNull())
1839 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1844 std::make_shared<Ledger>(seq, closeTime, *config_, nodeFamily_);
1845 loadLedger->setTotalDrops(totalDrops);
1847 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1853 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1861 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1871 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1879 if (!loadLedger->addSLE(sle))
1881 JLOG(m_journal.fatal())
1882 <<
"Couldn't add serialized ledger: " << uIndex;
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);
1900 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1906ApplicationImp::loadOldLedger(
1918 if (!ledgerID.
empty())
1919 loadLedger = loadLedgerFromFile(ledgerID);
1921 else if (ledgerID.
length() == 64)
1925 if (
hash.parseHex(ledgerID))
1932 auto il = std::make_shared<InboundLedger>(
1936 InboundLedger::Reason::GENERIC,
1939 if (il->checkLocal())
1940 loadLedger = il->getLedger();
1944 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1946 loadLedger = getLastFullLedger();
1965 replayLedger = loadLedger;
1967 JLOG(m_journal.info()) <<
"Loading parent ledger";
1969 loadLedger =
loadByHash(replayLedger->info().parentHash, *
this);
1972 JLOG(m_journal.info())
1973 <<
"Loading parent ledger from node store";
1976 auto il = std::make_shared<InboundLedger>(
1978 replayLedger->info().parentHash,
1980 InboundLedger::Reason::GENERIC,
1984 if (il->checkLocal())
1985 loadLedger = il->getLedger();
1989 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1991 "ripple::ApplicationImp::loadOldLedger : replay ledger "
1997 using namespace std::chrono_literals;
1998 using namespace date;
2000 sys_days{January / 1 / 2018} - sys_days{January / 1 / 2000}};
2001 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
2003 JLOG(m_journal.fatal())
2004 <<
"\n\n*** WARNING ***\n"
2005 "You are replaying a ledger from before "
2006 << to_string(ledgerWarnTimePoint)
2008 "This replay will not handle your ledger as it was "
2010 "handled.\nConsider running an earlier version of rippled "
2012 "get the older rules.\n*** CONTINUING ***\n";
2015 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->info().hash
2016 <<
" seq:" << loadLedger->info().seq;
2018 if (loadLedger->info().accountHash.isZero())
2020 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
2022 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2026 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
2028 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
2030 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2035 if (!loadLedger->assertSensible(journal(
"Ledger")))
2037 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
2039 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2044 m_ledgerMaster->setLedgerRangePresent(
2045 loadLedger->info().seq, loadLedger->info().seq);
2047 m_ledgerMaster->switchLCL(loadLedger);
2048 loadLedger->setValidated();
2049 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
2050 openLedger_.emplace(
2051 loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
2058 std::make_unique<LedgerReplay>(loadLedger, replayLedger);
2060 for (
auto const& [_, tx] : replayData->orderedTxns())
2063 auto txID = tx->getTransactionID();
2064 if (trapTxID == txID)
2067 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
2070 auto s = std::make_shared<Serializer>();
2073 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2075 openLedger_->modify(
2082 m_ledgerMaster->takeReplay(std::move(replayData));
2084 if (trapTxID && !trapTxID_)
2086 JLOG(m_journal.fatal())
2087 <<
"Ledger " << replayLedger->info().seq
2088 <<
" does not contain the transaction hash " << *trapTxID;
2095 JLOG(m_journal.fatal())
2096 <<
"While loading specified ledger: " << mn.
what();
2099 catch (boost::bad_lexical_cast&)
2101 JLOG(m_journal.fatal())
2102 <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2112 if (!config().ELB_SUPPORT)
2117 reason =
"Server is shutting down";
2121 if (getOPs().isNeedNetworkLedger())
2123 reason =
"Not synchronized with network yet";
2127 if (getOPs().isAmendmentBlocked())
2129 reason =
"Server version too old";
2133 if (getOPs().isUNLBlocked())
2135 reason =
"No valid validator list available";
2139 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2141 reason =
"Not synchronized with network";
2145 if (!getLedgerMaster().isCaughtUp(reason))
2148 if (getFeeTrack().isLoadedLocal())
2150 reason =
"Too much load";
2160 return logs_->journal(name);
2164ApplicationImp::setMaxDisallowedLedger()
2166 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2168 maxDisallowedLedger_ = *seq;
2170 JLOG(m_journal.trace())
2171 <<
"Max persisted ledger is " << maxDisallowedLedger_;
2188 return std::make_unique<ApplicationImp>(
2189 std::move(config), std::move(logs), std::move(timeKeeper));
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
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::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
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()