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>
60#include <xrpl/basics/ByteUtilities.h>
61#include <xrpl/basics/ResolverAsio.h>
62#include <xrpl/basics/random.h>
63#include <xrpl/beast/asio/io_latency_probe.h>
64#include <xrpl/beast/core/LexicalCast.h>
65#include <xrpl/crypto/csprng.h>
66#include <xrpl/json/json_reader.h>
67#include <xrpl/protocol/BuildInfo.h>
68#include <xrpl/protocol/Feature.h>
69#include <xrpl/protocol/Protocol.h>
70#include <xrpl/protocol/STParsedJSON.h>
71#include <xrpl/resource/Fees.h>
73#include <boost/algorithm/string/predicate.hpp>
74#include <boost/asio/steady_timer.hpp>
75#include <boost/system/error_code.hpp>
111 boost::asio::io_service& ios)
125 template <
class Duration>
130 auto const lastSample = ceil<milliseconds>(elapsed);
134 if (lastSample >= 10ms)
136 if (lastSample >= 500ms)
139 <<
"io_service latency = " << lastSample.count();
245#if RIPPLE_SINGLE_IO_SERVICE_THREAD
293 config_->section(SECTION_INSIGHT),
294 logs_->journal(
"Collector")))
320 logs_->journal(
"JobQueue"),
329 logs_->journal(
"SHAMapStore")))
336 logs_->journal(
"TaggedCache"))
343 logs_->journal(
"CachedSLEs"))
349 logs_->journal(
"Resource")))
397 logs_->journal(
"TaggedCache"))
409 logs_->journal(
"NetworkOPs"),
415 logs_->journal(
"PeerReservationTable")))
427 config_->legacy(
"database_path"),
428 logs_->journal(
"ValidatorList"),
452 logs_->journal(
"Validations"))
472 logs_->journal(
"Application"),
502 setup(boost::program_options::variables_map
const& cmdline)
override;
504 start(
bool withTimers)
override;
569 "Accessing Application::nodeIdentity() before it is initialized.");
592 "ripple::ApplicationImp::getServerHandler : non-null server "
597 boost::asio::io_service&
800 overlay_,
"ripple::ApplicationImp::overlay : non-null overlay");
809 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
818 "ripple::ApplicationImp::getRelationalDatabase : non-null "
819 "relational database");
828 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
845 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
855 setup.useGlobalPragma =
false;
862 <<
"Failed to initialize SQL databases: " << e.
what();
874 auto j =
logs_->journal(
"NodeObject");
885 JLOG(j.warn()) <<
"Starting node import from '" << source->getName()
889 auto const start = steady_clock::now();
894 duration_cast<seconds>(steady_clock::now() -
start);
895 JLOG(j.warn()) <<
"Node import from '" << source->getName()
896 <<
"' took " << elapsed.count() <<
" seconds.";
919 [
this](boost::system::error_code
const& e) {
920 if (e.value() == boost::system::errc::success)
923 jtSWEEP,
"sweep", [this]() { doSweep(); });
926 if (e.value() != boost::system::errc::success &&
927 e.value() != boost::asio::error::operation_aborted)
930 JLOG(m_journal.error())
931 <<
"Sweep timer got error '" << e.message()
932 <<
"'. Restarting timer.";
941 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
949 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
950 [
this](boost::system::error_code
const& e) {
951 if (e.value() == boost::system::errc::success)
953 crypto_prng().mix_entropy();
957 if (e.value() != boost::system::errc::success &&
958 e.value() != boost::asio::error::operation_aborted)
961 JLOG(m_journal.error())
962 <<
"Entropy timer got error '" << e.message()
963 <<
"'. Restarting timer.";
968 using namespace std::chrono_literals;
969 entropyTimer_.expires_from_now(5min);
970 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
977 if (!config_->standalone() &&
978 !getRelationalDatabase().transactionDbHasSpace(*config_))
980 signalStop(
"Out of transaction DB space");
989 nodeFamily_.getFullBelowCache();
992 nodeFamily_.getTreeNodeCache();
994 std::size_t const oldFullBelowSize = fullBelowCache->size();
995 std::size_t const oldTreeNodeSize = treeNodeCache->size();
999 JLOG(m_journal.debug())
1000 <<
"NodeFamily::FullBelowCache sweep. Size before: "
1002 <<
"; size after: " << fullBelowCache->size();
1004 JLOG(m_journal.debug())
1005 <<
"NodeFamily::TreeNodeCache sweep. Size before: "
1006 << oldTreeNodeSize <<
"; size after: " << treeNodeCache->size();
1010 getMasterTransaction().getCache();
1014 getMasterTransaction().sweep();
1016 JLOG(m_journal.debug())
1017 <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
1018 <<
"; size after: " << masterTxCache.
size();
1022 getNodeStore().sweep();
1026 getLedgerMaster().getFetchPackCacheSize();
1028 getLedgerMaster().sweep();
1030 JLOG(m_journal.debug())
1031 <<
"LedgerMaster sweep. Size before: "
1032 << oldLedgerMasterCacheSize <<
"; size after: "
1033 << getLedgerMaster().getFetchPackCacheSize();
1037 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1039 getTempNodeCache().sweep();
1041 JLOG(m_journal.debug())
1042 <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1043 <<
"; size after: " << getTempNodeCache().size();
1047 getValidations().sizeOfCurrentCache();
1049 getValidations().sizeOfSeqEnforcersCache();
1051 getValidations().sizeOfByLedgerCache();
1053 getValidations().sizeOfBySequenceCache();
1055 getValidations().expire(m_journal);
1057 JLOG(m_journal.debug())
1058 <<
"Validations Current expire. Size before: "
1059 << oldCurrentCacheSize
1060 <<
"; size after: " << getValidations().sizeOfCurrentCache();
1062 JLOG(m_journal.debug())
1063 <<
"Validations SeqEnforcer expire. Size before: "
1064 << oldSizeSeqEnforcesSize <<
"; size after: "
1065 << getValidations().sizeOfSeqEnforcersCache();
1067 JLOG(m_journal.debug())
1068 <<
"Validations ByLedger expire. Size before: "
1070 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1072 JLOG(m_journal.debug())
1073 <<
"Validations BySequence expire. Size before: "
1074 << oldBySequenceSize
1075 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1079 getInboundLedgers().cacheSize();
1081 getInboundLedgers().sweep();
1083 JLOG(m_journal.debug())
1084 <<
"InboundLedgers sweep. Size before: "
1085 << oldInboundLedgersSize
1086 <<
"; size after: " << getInboundLedgers().cacheSize();
1089 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1090 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1091 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1093 getLedgerReplayer().sweep();
1095 JLOG(m_journal.debug())
1096 <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1097 <<
"; size after: " << getLedgerReplayer().tasksSize();
1099 JLOG(m_journal.debug())
1100 <<
"LedgerReplayer deltas sweep. Size before: "
1102 <<
"; size after: " << getLedgerReplayer().deltasSize();
1104 JLOG(m_journal.debug())
1105 <<
"LedgerReplayer skipLists sweep. Size before: "
1107 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1111 m_acceptedLedgerCache.size();
1113 m_acceptedLedgerCache.sweep();
1115 JLOG(m_journal.debug())
1116 <<
"AcceptedLedgerCache sweep. Size before: "
1117 << oldAcceptedLedgerSize
1118 <<
"; size after: " << m_acceptedLedgerCache.size();
1121 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1123 cachedSLEs_.sweep();
1125 JLOG(m_journal.debug())
1126 <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1127 <<
"; size after: " << cachedSLEs_.size();
1137 return maxDisallowedLedger_;
1152 startGenesisLedger();
1155 getLastFullLedger();
1168 setMaxDisallowedLedger();
1175ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1185 m_signals.add(SIGINT);
1186 m_signals.add(SIGTERM);
1187 m_signals.async_wait(
1188 [
this](boost::system::error_code
const& ec,
int signum) {
1190 if (ec == boost::asio::error::operation_aborted)
1193 JLOG(m_journal.info()) <<
"Received signal " << signum;
1195 if (signum == SIGTERM || signum == SIGINT)
1196 signalStop(
"Signal: " + to_string(signum));
1199 auto debug_log = config_->getDebugLogFile();
1201 if (!debug_log.empty())
1206 if (!logs_->open(debug_log))
1207 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1210 if (logs_->threshold() > kDebug)
1211 logs_->threshold(kDebug);
1214 JLOG(m_journal.info()) <<
"Process starting: "
1215 << BuildInfo::getFullVersionString()
1216 <<
", Instance Cookie: " << instanceCookie_;
1218 if (numberOfThreads(*config_) < 2)
1220 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1221 "system configuration.";
1225 logs_->silent(config_->silent());
1227 if (!initRelationalDatabase() || !initNodeStore())
1230 if (!peerReservations_->load(getWalletDB()))
1232 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1236 if (validatorKeys_.keys)
1237 setMaxDisallowedLedger();
1241 auto const supported = []() {
1242 auto const& amendments = detail::supportedAmendments();
1244 supported.reserve(amendments.size());
1245 for (
auto const& [a, vote] : amendments)
1249 f,
"ripple::ApplicationImp::setup : registered feature");
1251 supported.emplace_back(a, *f, vote);
1255 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1257 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1261 config().AMENDMENT_MAJORITY_TIME,
1265 logs_->journal(
"Amendments"));
1268 Pathfinder::initPathTable();
1270 auto const startUp = config_->START_UP;
1271 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1272 if (startUp == Config::FRESH)
1274 JLOG(m_journal.info()) <<
"Starting new Ledger";
1276 startGenesisLedger();
1279 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1280 startUp == Config::REPLAY)
1282 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1285 config_->START_LEDGER,
1286 startUp == Config::REPLAY,
1287 startUp == Config::LOAD_FILE,
1288 config_->TRAP_TX_HASH))
1290 JLOG(m_journal.error())
1291 <<
"The specified ledger could not be loaded.";
1292 if (config_->FAST_LOAD)
1296 startGenesisLedger();
1304 else if (startUp == Config::NETWORK)
1308 if (!config_->standalone())
1309 m_networkOPs->setNeedNetworkLedger();
1311 startGenesisLedger();
1315 startGenesisLedger();
1318 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1320 m_ledgerMaster->setLedgerRangePresent(
1321 forcedRange->first, forcedRange->second);
1324 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1328 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1330 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1335 if (validatorKeys_.configInvalid())
1338 if (!validatorManifests_->load(
1340 "ValidatorManifests",
1341 validatorKeys_.manifest,
1342 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1344 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1348 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1357 if (validatorKeys_.keys)
1358 localSigningKey = validatorKeys_.keys->publicKey;
1361 if (!validators_->load(
1363 config().section(SECTION_VALIDATORS).values(),
1364 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1365 config().VALIDATOR_LIST_THRESHOLD))
1367 JLOG(m_journal.fatal())
1368 <<
"Invalid entry in validator configuration.";
1373 if (!validatorSites_->load(
1374 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1376 JLOG(m_journal.fatal())
1377 <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1382 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1403 m_collectorManager->collector());
1407 if (!m_networkOPs->beginConsensus(
1408 m_ledgerMaster->getClosedLedger()->info().hash, {}))
1410 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1420 serverHandler_->setup(setup, m_journal);
1425 if (
auto stream = m_journal.fatal())
1427 stream <<
"Unable to setup server handler";
1429 stream <<
": " << e.
what();
1436 if (!config_->standalone())
1440 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1442 JLOG(m_journal.warn())
1443 <<
"No outbound peer connections will be made";
1448 m_networkOPs->setStateTimer();
1452 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1454 m_networkOPs->setStandAlone();
1457 if (config_->canSign())
1459 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1460 "'sign' and 'sign_for'";
1461 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1462 "implications and have";
1463 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1464 "in a future release of";
1465 JLOG(m_journal.warn()) <<
"*** rippled.";
1466 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1467 "transactions please edit your";
1468 JLOG(m_journal.warn())
1469 <<
"*** configuration file and remove the [enable_signing] stanza.";
1470 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1471 "please migrate to a";
1472 JLOG(m_journal.warn())
1473 <<
"*** standalone signing solution as soon as possible.";
1479 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1484 if (!jrReader.
parse(cmd, jvCommand))
1486 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in ["
1487 << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1490 if (!config_->quiet())
1492 JLOG(m_journal.fatal())
1493 <<
"Startup RPC: " << jvCommand <<
std::endl;
1499 {journal(
"RPCHandler"),
1508 RPC::apiMaximumSupportedVersion},
1512 RPC::doCommand(context, jvResult);
1514 if (!config_->quiet())
1516 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1520 validatorSites_->start();
1526ApplicationImp::start(
bool withTimers)
1528 JLOG(m_journal.info()) <<
"Application starting. Version is "
1529 << BuildInfo::getVersionString();
1537 m_io_latency_sampler.start();
1538 m_resolver->start();
1539 m_loadManager->start();
1540 m_shaMapStore->start();
1544 if (grpcServer_->start())
1546 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1548 ledgerCleaner_->start();
1553ApplicationImp::run()
1555 if (!config_->standalone())
1561 getLoadManager().activateStallDetector();
1566 stoppingCondition_.wait(lk, [
this] {
return isTimeToStop.load(); });
1569 JLOG(m_journal.debug()) <<
"Application stopping";
1571 m_io_latency_sampler.cancel_async();
1579 m_io_latency_sampler.cancel();
1581 m_resolver->stop_async();
1589 boost::system::error_code ec;
1590 sweepTimer_.cancel(ec);
1593 JLOG(m_journal.error())
1594 <<
"Application: sweepTimer cancel error: " << ec.message();
1598 entropyTimer_.cancel(ec);
1601 JLOG(m_journal.error())
1602 <<
"Application: entropyTimer cancel error: " << ec.message();
1608 using namespace std::chrono_literals;
1610 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1612 mValidations.flush();
1614 validatorSites_->stop();
1617 validatorManifests_->save(
1618 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1619 return validators().listed(pubKey);
1622 publisherManifests_->save(
1623 getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1624 return validators().trustedPublisher(pubKey);
1629 m_loadManager->stop();
1630 m_shaMapStore->stop();
1634 grpcServer_->stop();
1635 m_networkOPs->stop();
1636 serverHandler_->stop();
1637 m_ledgerReplayer->stop();
1638 m_inboundTransactions->stop();
1639 m_inboundLedgers->stop();
1640 ledgerCleaner_->stop();
1641 m_nodeStore->stop();
1644 JLOG(m_journal.info()) <<
"Done.";
1650 if (!isTimeToStop.exchange(
true))
1653 JLOG(m_journal.warn()) <<
"Server stopping";
1655 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1657 stoppingCondition_.notify_all();
1662ApplicationImp::checkSigs()
const
1668ApplicationImp::checkSigs(
bool check)
1674ApplicationImp::isStopping()
const
1676 return isTimeToStop.load();
1680ApplicationImp::fdRequired()
const
1687 needed += 2 * overlay_->limit();
1691 needed +=
std::max(5, m_shaMapStore->fdRequired());
1695 for (
auto const& p : serverHandler_->setup().ports)
1705ApplicationImp::startGenesisLedger()
1708 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1713 m_ledgerMaster->storeLedger(genesis);
1717 next->updateSkipList();
1719 next->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1720 next->read(keylet::fees()),
1721 "ripple::ApplicationImp::startGenesisLedger : valid ledger fees");
1722 next->setImmutable();
1723 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1724 m_ledgerMaster->storeLedger(next);
1725 m_ledgerMaster->switchLCL(next);
1729ApplicationImp::getLastFullLedger()
1731 auto j = journal(
"Ledger");
1741 ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1742 ledger->read(keylet::fees()),
1743 "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
1744 ledger->setImmutable();
1746 if (getLedgerMaster().haveLedger(seq))
1747 ledger->setValidated();
1749 if (ledger->info().hash ==
hash)
1751 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1755 if (
auto stream = j.error())
1757 stream <<
"Failed on ledger";
1759 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1767 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1781 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1788 if (!reader.
parse(ledgerFile, jLedger))
1790 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1797 if (ledger.
get().isMember(
"result"))
1798 ledger = ledger.
get()[
"result"];
1800 if (ledger.
get().isMember(
"ledger"))
1801 ledger = ledger.
get()[
"ledger"];
1804 auto closeTime = timeKeeper().closeTime();
1805 using namespace std::chrono_literals;
1806 auto closeTimeResolution = 30s;
1807 bool closeTimeEstimated =
false;
1810 if (ledger.
get().isMember(
"accountState"))
1812 if (ledger.
get().isMember(jss::ledger_index))
1814 seq = ledger.
get()[jss::ledger_index].asUInt();
1817 if (ledger.
get().isMember(
"close_time"))
1820 using d = tp::duration;
1821 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1823 if (ledger.
get().isMember(
"close_time_resolution"))
1826 closeTimeResolution =
1827 seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1829 if (ledger.
get().isMember(
"close_time_estimated"))
1831 closeTimeEstimated =
1832 ledger.
get()[
"close_time_estimated"].asBool();
1834 if (ledger.
get().isMember(
"total_coins"))
1836 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1837 ledger.
get()[
"total_coins"].asString());
1840 ledger = ledger.
get()[
"accountState"];
1843 if (!ledger.
get().isArrayOrNull())
1845 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1851 loadLedger->setTotalDrops(totalDrops);
1853 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1859 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1867 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1877 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1885 if (!loadLedger->addSLE(sle))
1887 JLOG(m_journal.fatal())
1888 <<
"Couldn't add serialized ledger: " << uIndex;
1896 loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1897 loadLedger->read(keylet::fees()),
1898 "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1899 loadLedger->setAccepted(
1900 closeTime, closeTimeResolution, !closeTimeEstimated);
1906 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1912ApplicationImp::loadOldLedger(
1924 if (!ledgerID.
empty())
1925 loadLedger = loadLedgerFromFile(ledgerID);
1927 else if (ledgerID.
length() == 64)
1931 if (
hash.parseHex(ledgerID))
1942 InboundLedger::Reason::GENERIC,
1945 if (il->checkLocal())
1946 loadLedger = il->getLedger();
1950 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1952 loadLedger = getLastFullLedger();
1971 replayLedger = loadLedger;
1973 JLOG(m_journal.info()) <<
"Loading parent ledger";
1975 loadLedger =
loadByHash(replayLedger->info().parentHash, *
this);
1978 JLOG(m_journal.info())
1979 <<
"Loading parent ledger from node store";
1984 replayLedger->info().parentHash,
1986 InboundLedger::Reason::GENERIC,
1990 if (il->checkLocal())
1991 loadLedger = il->getLedger();
1995 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1997 "ripple::ApplicationImp::loadOldLedger : replay ledger "
2003 using namespace std::chrono_literals;
2004 using namespace date;
2007 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
2009 JLOG(m_journal.fatal())
2010 <<
"\n\n*** WARNING ***\n"
2011 "You are replaying a ledger from before "
2012 << to_string(ledgerWarnTimePoint)
2014 "This replay will not handle your ledger as it was "
2016 "handled.\nConsider running an earlier version of rippled "
2018 "get the older rules.\n*** CONTINUING ***\n";
2021 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->info().hash
2022 <<
" seq:" << loadLedger->info().seq;
2024 if (loadLedger->info().accountHash.isZero())
2026 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
2028 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2032 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
2034 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
2036 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2041 if (!loadLedger->assertSensible(journal(
"Ledger")))
2043 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
2045 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2050 m_ledgerMaster->setLedgerRangePresent(
2051 loadLedger->info().seq, loadLedger->info().seq);
2053 m_ledgerMaster->switchLCL(loadLedger);
2054 loadLedger->setValidated();
2055 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
2056 openLedger_.emplace(
2057 loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
2066 for (
auto const& [_, tx] : replayData->orderedTxns())
2069 auto txID = tx->getTransactionID();
2070 if (trapTxID == txID)
2073 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
2079 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2081 openLedger_->modify(
2088 m_ledgerMaster->takeReplay(std::move(replayData));
2090 if (trapTxID && !trapTxID_)
2092 JLOG(m_journal.fatal())
2093 <<
"Ledger " << replayLedger->info().seq
2094 <<
" does not contain the transaction hash " << *trapTxID;
2101 JLOG(m_journal.fatal())
2102 <<
"While loading specified ledger: " << mn.
what();
2105 catch (boost::bad_lexical_cast&)
2107 JLOG(m_journal.fatal())
2108 <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2118 if (!config().ELB_SUPPORT)
2123 reason =
"Server is shutting down";
2127 if (getOPs().isNeedNetworkLedger())
2129 reason =
"Not synchronized with network yet";
2133 if (getOPs().isAmendmentBlocked())
2135 reason =
"Server version too old";
2139 if (getOPs().isUNLBlocked())
2141 reason =
"No valid validator list available";
2145 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2147 reason =
"Not synchronized with network";
2151 if (!getLedgerMaster().isCaughtUp(reason))
2154 if (getFeeTrack().isLoadedLocal())
2156 reason =
"Too much load";
2166 return logs_->journal(name);
2170ApplicationImp::setMaxDisallowedLedger()
2172 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2174 maxDisallowedLedger_ = *seq;
2176 JLOG(m_journal.trace())
2177 <<
"Max persisted ledger is " << maxDisallowedLedger_;
2195 std::move(config), std::move(logs), std::move(timeKeeper));
2201 for (
auto const& [name, ep] : endpoints)
2203 if (!config.
exists(name))
2206 auto& section = config[name];
2207 auto const optPort = section.get(
"port");
2211 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(char const *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
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
Overlay & overlay() override
ValidatorList & validators() override
ValidatorSite & validatorSites() override
virtual std::optional< uint256 > const & trapTxID() const 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_
void signalStop(std::string msg) override
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.
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)
HashRouter::Setup setup_HashRouter(Config const &config)
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()