1#include <xrpld/app/consensus/RCLValidations.h>
2#include <xrpld/app/ledger/InboundLedgers.h>
3#include <xrpld/app/ledger/InboundTransactions.h>
4#include <xrpld/app/ledger/LedgerCleaner.h>
5#include <xrpld/app/ledger/LedgerMaster.h>
6#include <xrpld/app/ledger/LedgerReplayer.h>
7#include <xrpld/app/ledger/LedgerToJson.h>
8#include <xrpld/app/ledger/OpenLedger.h>
9#include <xrpld/app/ledger/OrderBookDBImpl.h>
10#include <xrpld/app/ledger/PendingSaves.h>
11#include <xrpld/app/ledger/TransactionMaster.h>
12#include <xrpld/app/main/Application.h>
13#include <xrpld/app/main/BasicApp.h>
14#include <xrpld/app/main/GRPCServer.h>
15#include <xrpld/app/main/LoadManager.h>
16#include <xrpld/app/main/NodeIdentity.h>
17#include <xrpld/app/main/NodeStoreScheduler.h>
18#include <xrpld/app/misc/SHAMapStore.h>
19#include <xrpld/app/misc/TxQ.h>
20#include <xrpld/app/misc/ValidatorKeys.h>
21#include <xrpld/app/misc/ValidatorSite.h>
22#include <xrpld/app/misc/make_NetworkOPs.h>
23#include <xrpld/app/misc/setup_HashRouter.h>
24#include <xrpld/app/paths/PathRequests.h>
25#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
26#include <xrpld/core/ConfigSections.h>
27#include <xrpld/core/NetworkIDServiceImpl.h>
28#include <xrpld/overlay/Cluster.h>
29#include <xrpld/overlay/PeerSet.h>
30#include <xrpld/overlay/make_Overlay.h>
31#include <xrpld/shamap/NodeFamily.h>
33#include <xrpl/basics/ByteUtilities.h>
34#include <xrpl/basics/ResolverAsio.h>
35#include <xrpl/basics/random.h>
36#include <xrpl/beast/asio/io_latency_probe.h>
37#include <xrpl/beast/core/LexicalCast.h>
38#include <xrpl/core/HashRouter.h>
39#include <xrpl/core/PeerReservationTable.h>
40#include <xrpl/core/PerfLog.h>
41#include <xrpl/crypto/csprng.h>
42#include <xrpl/json/json_reader.h>
43#include <xrpl/ledger/AmendmentTable.h>
44#include <xrpl/nodestore/DummyScheduler.h>
45#include <xrpl/protocol/ApiVersion.h>
46#include <xrpl/protocol/BuildInfo.h>
47#include <xrpl/protocol/Feature.h>
48#include <xrpl/protocol/Protocol.h>
49#include <xrpl/protocol/STParsedJSON.h>
50#include <xrpl/rdb/DatabaseCon.h>
51#include <xrpl/resource/Fees.h>
52#include <xrpl/server/LoadFeeTrack.h>
53#include <xrpl/server/Wallet.h>
54#include <xrpl/tx/apply.h>
56#include <boost/algorithm/string/predicate.hpp>
57#include <boost/asio/steady_timer.hpp>
58#include <boost/system/error_code.hpp>
93 boost::asio::io_context& ios)
104 template <
class Duration>
109 auto const lastSample = ceil<milliseconds>(elapsed);
113 if (lastSample >= 10ms)
115 if (lastSample >= 500ms)
117 JLOG(
m_journal.
warn()) <<
"io_context latency = " << lastSample.count();
219#if XRPL_SINGLE_IO_SERVICE_THREAD
255 perf::setup_PerfLog(
config_->section(
"perf"),
config_->CONFIG_DIR),
289 logs_->journal(
"JobQueue"),
303 logs_->journal(
"TaggedCache"))
310 logs_->journal(
"CachedSLEs"))
329 logs_->journal(
"PathRequest"),
337 logs_->journal(
"LedgerMaster")))
350 gotTXSet(set, fromAcquire);
364 logs_->journal(
"TaggedCache"))
376 logs_->journal(
"NetworkOPs"),
393 config_->legacy(
"database_path"),
394 logs_->journal(
"ValidatorList"),
429 logs_->journal(
"Application"),
459 setup(boost::program_options::variables_map
const& cmdline)
override;
461 start(
bool withTimers)
override;
525 LogicError(
"Accessing Application::nodeIdentity() before it is initialized.");
548 "xrpl::ApplicationImp::getServerHandler : non-null server "
553 boost::asio::io_context&
761 XRPL_ASSERT(
overlay_,
"xrpl::ApplicationImp::overlay : non-null overlay");
768 XRPL_ASSERT(
txQ_,
"xrpl::ApplicationImp::getTxQ : non-null transaction queue");
777 "xrpl::ApplicationImp::getRelationalDatabase : non-null "
778 "relational database");
785 XRPL_ASSERT(
mWalletDB,
"xrpl::ApplicationImp::getWalletDB : non-null wallet database");
802 "xrpl::ApplicationImp::initRelationalDatabase : null wallet "
811 setup.useGlobalPragma =
false;
829 auto j =
logs_->journal(
"NodeObject");
839 JLOG(j.warn()) <<
"Starting node import from '" << source->getName() <<
"' to '"
843 auto const start = steady_clock::now();
847 auto const elapsed = duration_cast<seconds>(steady_clock::now() -
start);
848 JLOG(j.warn()) <<
"Node import from '" << source->getName() <<
"' took "
849 << elapsed.count() <<
" seconds.";
871 if (
auto optionalCountedHandler =
873 if (e.value() == boost::system::errc::success)
875 m_jobQueue->addJob(jtSWEEP,
"sweep", [this]() { doSweep(); });
878 if (e.value() != boost::system::errc::success &&
879 e.value() != boost::asio::error::operation_aborted)
882 JLOG(m_journal.error())
883 <<
"Sweep timer got error '" << e.message() <<
"'. Restarting timer.";
892 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
900 if (
auto optionalCountedHandler =
901 waitHandlerCounter_.wrap([
this](boost::system::error_code
const& e) {
902 if (e.value() == boost::system::errc::success)
904 crypto_prng().mix_entropy();
908 if (e.value() != boost::system::errc::success &&
909 e.value() != boost::asio::error::operation_aborted)
912 JLOG(m_journal.error()) <<
"Entropy timer got error '" << e.message()
913 <<
"'. Restarting timer.";
918 using namespace std::chrono_literals;
919 entropyTimer_.expires_after(5min);
920 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
928 relationalDatabase_,
"xrpl::ApplicationImp::doSweep : non-null relational database");
929 if (!config_->standalone() && !relationalDatabase_->transactionDbHasSpace(*config_))
931 signalStop(
"Out of transaction DB space");
940 nodeFamily_.getFullBelowCache();
943 nodeFamily_.getTreeNodeCache();
945 std::size_t const oldFullBelowSize = fullBelowCache->size();
946 std::size_t const oldTreeNodeSize = treeNodeCache->size();
950 JLOG(m_journal.debug())
951 <<
"NodeFamily::FullBelowCache sweep. Size before: " << oldFullBelowSize
952 <<
"; size after: " << fullBelowCache->size();
954 JLOG(m_journal.debug())
955 <<
"NodeFamily::TreeNodeCache sweep. Size before: " << oldTreeNodeSize
956 <<
"; size after: " << treeNodeCache->size();
960 getMasterTransaction().getCache();
964 getMasterTransaction().sweep();
966 JLOG(m_journal.debug()) <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
967 <<
"; size after: " << masterTxCache.
size();
970 std::size_t const oldLedgerMasterCacheSize = getLedgerMaster().getFetchPackCacheSize();
972 getLedgerMaster().sweep();
974 JLOG(m_journal.debug())
975 <<
"LedgerMaster sweep. Size before: " << oldLedgerMasterCacheSize
976 <<
"; size after: " << getLedgerMaster().getFetchPackCacheSize();
980 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
982 getTempNodeCache().sweep();
984 JLOG(m_journal.debug()) <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
985 <<
"; size after: " << getTempNodeCache().size();
988 std::size_t const oldCurrentCacheSize = getValidations().sizeOfCurrentCache();
989 std::size_t const oldSizeSeqEnforcesSize = getValidations().sizeOfSeqEnforcersCache();
990 std::size_t const oldByLedgerSize = getValidations().sizeOfByLedgerCache();
991 std::size_t const oldBySequenceSize = getValidations().sizeOfBySequenceCache();
993 getValidations().expire(m_journal);
995 JLOG(m_journal.debug())
996 <<
"Validations Current expire. Size before: " << oldCurrentCacheSize
997 <<
"; size after: " << getValidations().sizeOfCurrentCache();
999 JLOG(m_journal.debug())
1000 <<
"Validations SeqEnforcer expire. Size before: " << oldSizeSeqEnforcesSize
1001 <<
"; size after: " << getValidations().sizeOfSeqEnforcersCache();
1003 JLOG(m_journal.debug())
1004 <<
"Validations ByLedger expire. Size before: " << oldByLedgerSize
1005 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1007 JLOG(m_journal.debug())
1008 <<
"Validations BySequence expire. Size before: " << oldBySequenceSize
1009 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1012 std::size_t const oldInboundLedgersSize = getInboundLedgers().cacheSize();
1014 getInboundLedgers().sweep();
1016 JLOG(m_journal.debug())
1017 <<
"InboundLedgers sweep. Size before: " << oldInboundLedgersSize
1018 <<
"; size after: " << getInboundLedgers().cacheSize();
1021 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1022 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1023 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1025 getLedgerReplayer().sweep();
1027 JLOG(m_journal.debug()) <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1028 <<
"; size after: " << getLedgerReplayer().tasksSize();
1030 JLOG(m_journal.debug())
1031 <<
"LedgerReplayer deltas sweep. Size before: " << oldDeltasSize
1032 <<
"; size after: " << getLedgerReplayer().deltasSize();
1034 JLOG(m_journal.debug())
1035 <<
"LedgerReplayer skipLists sweep. Size before: " << oldSkipListsSize
1036 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1039 std::size_t const oldAcceptedLedgerSize = m_acceptedLedgerCache.size();
1041 m_acceptedLedgerCache.sweep();
1043 JLOG(m_journal.debug())
1044 <<
"AcceptedLedgerCache sweep. Size before: " << oldAcceptedLedgerSize
1045 <<
"; size after: " << m_acceptedLedgerCache.size();
1048 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1050 cachedSLEs_.sweep();
1052 JLOG(m_journal.debug()) <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1053 <<
"; size after: " << cachedSLEs_.size();
1063 return maxDisallowedLedger_;
1078 startGenesisLedger();
1081 getLastFullLedger();
1094 setMaxDisallowedLedger();
1107ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1117 m_signals.
add(SIGINT);
1118 m_signals.add(SIGTERM);
1119 m_signals.async_wait([
this](boost::system::error_code
const& ec,
int signum) {
1121 if (ec == boost::asio::error::operation_aborted)
1124 JLOG(m_journal.info()) <<
"Received signal " << signum;
1126 if (signum == SIGTERM || signum == SIGINT)
1127 signalStop(
"Signal: " + to_string(signum));
1130 auto debug_log = config_->getDebugLogFile();
1132 if (!debug_log.empty())
1137 if (!logs_->open(debug_log))
1138 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1141 if (logs_->threshold() > kDebug)
1142 logs_->threshold(kDebug);
1145 JLOG(m_journal.info()) <<
"Process starting: " << BuildInfo::getFullVersionString()
1146 <<
", Instance Cookie: " << instanceCookie_;
1148 if (numberOfThreads(*config_) < 2)
1150 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1151 "system configuration.";
1155 logs_->silent(config_->silent());
1157 if (!initRelationalDatabase() || !initNodeStore())
1160 if (!peerReservations_->load(getWalletDB()))
1162 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1166 if (validatorKeys_.keys)
1167 setMaxDisallowedLedger();
1171 auto const supported = []() {
1172 auto const& amendments = detail::supportedAmendments();
1174 supported.reserve(amendments.size());
1175 for (
auto const& [a, vote] : amendments)
1178 XRPL_ASSERT(f,
"xrpl::ApplicationImp::setup : registered feature");
1180 supported.emplace_back(a, *f, vote);
1184 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1186 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1190 config().AMENDMENT_MAJORITY_TIME,
1194 logs_->journal(
"Amendments"));
1197 Pathfinder::initPathTable();
1199 auto const startUp = config_->START_UP;
1200 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1201 if (startUp == StartUpType::FRESH)
1203 JLOG(m_journal.info()) <<
"Starting new Ledger";
1205 startGenesisLedger();
1208 startUp == StartUpType::LOAD || startUp == StartUpType::LOAD_FILE ||
1209 startUp == StartUpType::REPLAY)
1211 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1214 config_->START_LEDGER,
1215 startUp == StartUpType::REPLAY,
1216 startUp == StartUpType::LOAD_FILE,
1217 config_->TRAP_TX_HASH))
1219 JLOG(m_journal.error()) <<
"The specified ledger could not be loaded.";
1220 if (config_->FAST_LOAD)
1224 startGenesisLedger();
1232 else if (startUp == StartUpType::NETWORK)
1236 if (!config_->standalone())
1237 m_networkOPs->setNeedNetworkLedger();
1239 startGenesisLedger();
1243 startGenesisLedger();
1246 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1248 m_ledgerMaster->setLedgerRangePresent(forcedRange->first, forcedRange->second);
1251 m_orderBookDB->setup(getLedgerMaster().getCurrentLedger());
1255 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1257 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1262 if (validatorKeys_.configInvalid())
1265 if (!validatorManifests_->load(
1267 "ValidatorManifests",
1268 validatorKeys_.manifest,
1269 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1271 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1275 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1284 if (validatorKeys_.keys)
1285 localSigningKey = validatorKeys_.keys->publicKey;
1288 if (!validators_->load(
1290 config().section(SECTION_VALIDATORS).values(),
1291 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1292 config().VALIDATOR_LIST_THRESHOLD))
1294 JLOG(m_journal.fatal()) <<
"Invalid entry in validator configuration.";
1299 if (!validatorSites_->load(config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1301 JLOG(m_journal.fatal()) <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1306 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1327 m_collectorManager->collector());
1331 if (!m_networkOPs->beginConsensus(m_ledgerMaster->getClosedLedger()->header().hash, {}))
1333 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1342 serverHandler_->setup(setup, m_journal);
1347 if (
auto stream = m_journal.fatal())
1349 stream <<
"Unable to setup server handler";
1351 stream <<
": " << e.
what();
1358 if (!config_->standalone())
1362 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1364 JLOG(m_journal.warn()) <<
"No outbound peer connections will be made";
1369 m_networkOPs->setStateTimer();
1373 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1375 m_networkOPs->setStandAlone();
1378 if (config_->canSign())
1380 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1381 "'sign' and 'sign_for'";
1382 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1383 "implications and have";
1384 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1385 "in a future release of";
1386 JLOG(m_journal.warn()) <<
"*** rippled.";
1387 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1388 "transactions please edit your";
1389 JLOG(m_journal.warn()) <<
"*** configuration file and remove the [enable_signing] stanza.";
1390 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1391 "please migrate to a";
1392 JLOG(m_journal.warn()) <<
"*** standalone signing solution as soon as possible.";
1398 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1403 if (!jrReader.
parse(cmd, jvCommand))
1405 JLOG(m_journal.fatal())
1406 <<
"Couldn't parse entry in [" << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1409 if (!config_->quiet())
1411 JLOG(m_journal.fatal()) <<
"Startup RPC: " << jvCommand <<
std::endl;
1417 {journal(
"RPCHandler"),
1426 RPC::apiMaximumSupportedVersion},
1430 RPC::doCommand(context, jvResult);
1432 if (!config_->quiet())
1434 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1438 validatorSites_->start();
1444ApplicationImp::start(
bool withTimers)
1446 JLOG(m_journal.info()) <<
"Application starting. Version is " << BuildInfo::getVersionString();
1454 m_io_latency_sampler.start();
1455 m_resolver->start();
1456 m_loadManager->start();
1457 m_shaMapStore->start();
1461 if (grpcServer_->start())
1462 fixConfigPorts(*config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1464 ledgerCleaner_->start();
1469ApplicationImp::run()
1471 if (!config_->standalone())
1477 getLoadManager().activateStallDetector();
1482 JLOG(m_journal.debug()) <<
"Application stopping";
1484 m_io_latency_sampler.cancel_async();
1492 m_io_latency_sampler.cancel();
1494 m_resolver->stop_async();
1504 sweepTimer_.cancel();
1506 catch (boost::system::system_error
const& e)
1508 JLOG(m_journal.error()) <<
"Application: sweepTimer cancel error: " << e.what();
1513 entropyTimer_.cancel();
1515 catch (boost::system::system_error
const& e)
1517 JLOG(m_journal.error()) <<
"Application: entropyTimer cancel error: " << e.what();
1523 using namespace std::chrono_literals;
1525 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1527 mValidations.flush();
1529 validatorSites_->stop();
1532 validatorManifests_->save(getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1533 return validators().listed(pubKey);
1536 publisherManifests_->save(getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1537 return validators().trustedPublisher(pubKey);
1542 m_loadManager->stop();
1543 m_shaMapStore->stop();
1547 grpcServer_->stop();
1548 m_networkOPs->stop();
1549 serverHandler_->stop();
1550 m_ledgerReplayer->stop();
1551 m_inboundTransactions->stop();
1552 m_inboundLedgers->stop();
1553 ledgerCleaner_->stop();
1554 m_nodeStore->stop();
1557 JLOG(m_journal.info()) <<
"Done.";
1566 JLOG(m_journal.warn()) <<
"Server stopping";
1568 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1570 isTimeToStop.notify_all();
1575ApplicationImp::checkSigs()
const
1581ApplicationImp::checkSigs(
bool check)
1587ApplicationImp::isStopping()
const
1593ApplicationImp::fdRequired()
const
1600 needed += 2 * overlay_->limit();
1604 needed +=
std::max(5, m_shaMapStore->fdRequired());
1608 for (
auto const& p : serverHandler_->setup().ports)
1618ApplicationImp::startGenesisLedger()
1621 ? m_amendmentTable->getDesired()
1626 m_ledgerMaster->storeLedger(genesis);
1629 next->updateSkipList();
1631 next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()),
1632 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1633 next->setImmutable();
1634 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1635 m_ledgerMaster->storeLedger(next);
1636 m_ledgerMaster->switchLCL(next);
1640ApplicationImp::getLastFullLedger()
1642 auto j = journal(
"Ledger");
1652 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
1653 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1654 ledger->setImmutable();
1656 if (getLedgerMaster().haveLedger(seq))
1657 ledger->setValidated();
1659 if (ledger->header().hash ==
hash)
1661 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1665 if (
auto stream = j.error())
1667 stream <<
"Failed on ledger";
1669 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1677 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1691 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1698 if (!reader.
parse(ledgerFile, jLedger))
1700 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1707 if (ledger.
get().isMember(
"result"))
1708 ledger = ledger.
get()[
"result"];
1710 if (ledger.
get().isMember(
"ledger"))
1711 ledger = ledger.
get()[
"ledger"];
1714 auto closeTime = timeKeeper().closeTime();
1715 using namespace std::chrono_literals;
1716 auto closeTimeResolution = 30s;
1717 bool closeTimeEstimated =
false;
1720 if (ledger.
get().isMember(
"accountState"))
1722 if (ledger.
get().isMember(jss::ledger_index))
1724 seq = ledger.
get()[jss::ledger_index].asUInt();
1727 if (ledger.
get().isMember(
"close_time"))
1730 using d = tp::duration;
1731 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1733 if (ledger.
get().isMember(
"close_time_resolution"))
1736 closeTimeResolution =
seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1738 if (ledger.
get().isMember(
"close_time_estimated"))
1740 closeTimeEstimated = ledger.
get()[
"close_time_estimated"].asBool();
1742 if (ledger.
get().isMember(
"total_coins"))
1745 beast::lexicalCastThrow<std::uint64_t>(ledger.
get()[
"total_coins"].asString());
1748 ledger = ledger.
get()[
"accountState"];
1751 if (!ledger.
get().isArrayOrNull())
1753 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1758 loadLedger->setTotalDrops(totalDrops);
1760 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1766 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1774 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1784 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1792 if (!loadLedger->addSLE(sle))
1794 JLOG(m_journal.fatal()) <<
"Couldn't add serialized ledger: " << uIndex;
1802 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()),
1803 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1804 loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated);
1810 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1816ApplicationImp::loadOldLedger(
1828 if (!ledgerID.
empty())
1829 loadLedger = loadLedgerFromFile(ledgerID);
1831 else if (ledgerID.
length() == 64)
1835 if (
hash.parseHex(ledgerID))
1846 InboundLedger::Reason::GENERIC,
1849 if (il->checkLocal())
1850 loadLedger = il->getLedger();
1854 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1856 loadLedger = getLastFullLedger();
1875 replayLedger = loadLedger;
1877 JLOG(m_journal.info()) <<
"Loading parent ledger";
1879 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1882 JLOG(m_journal.info()) <<
"Loading parent ledger from node store";
1887 replayLedger->header().parentHash,
1889 InboundLedger::Reason::GENERIC,
1893 if (il->checkLocal())
1894 loadLedger = il->getLedger();
1899 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1901 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1908 using namespace std::chrono_literals;
1909 using namespace date;
1912 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1914 JLOG(m_journal.fatal()) <<
"\n\n*** WARNING ***\n"
1915 "You are replaying a ledger from before "
1916 << to_string(ledgerWarnTimePoint)
1918 "This replay will not handle your ledger as it was "
1920 "handled.\nConsider running an earlier version of rippled "
1922 "get the older rules.\n*** CONTINUING ***\n";
1925 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash
1926 <<
" seq:" << loadLedger->header().seq;
1928 if (loadLedger->header().accountHash.isZero())
1931 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
1932 UNREACHABLE(
"xrpl::ApplicationImp::loadOldLedger : ledger is empty");
1937 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
1940 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
1942 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
1948 if (!loadLedger->assertSensible(journal(
"Ledger")))
1951 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
1953 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
1959 m_ledgerMaster->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq);
1961 m_ledgerMaster->switchLCL(loadLedger);
1962 loadLedger->setValidated();
1963 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
1964 openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
1972 for (
auto const& [_, tx] : replayData->orderedTxns())
1975 auto txID = tx->getTransactionID();
1976 if (trapTxID == txID)
1979 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
1985 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
1993 m_ledgerMaster->takeReplay(std::move(replayData));
1995 if (trapTxID && !trapTxID_)
1997 JLOG(m_journal.fatal()) <<
"Ledger " << replayLedger->header().seq
1998 <<
" does not contain the transaction hash " << *trapTxID;
2005 JLOG(m_journal.fatal()) <<
"While loading specified ledger: " << mn.
what();
2008 catch (boost::bad_lexical_cast&)
2010 JLOG(m_journal.fatal()) <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2020 if (!config().ELB_SUPPORT)
2025 reason =
"Server is shutting down";
2029 if (getOPs().isNeedNetworkLedger())
2031 reason =
"Not synchronized with network yet";
2035 if (getOPs().isAmendmentBlocked())
2037 reason =
"Server version too old";
2041 if (getOPs().isUNLBlocked())
2043 reason =
"No valid validator list available";
2047 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2049 reason =
"Not synchronized with network";
2053 if (!getLedgerMaster().isCaughtUp(reason))
2056 if (getFeeTrack().isLoadedLocal())
2058 reason =
"Too much load";
2068 return logs_->journal(name);
2072ApplicationImp::setMaxDisallowedLedger()
2074 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2076 maxDisallowedLedger_ = *seq;
2078 JLOG(m_journal.trace()) <<
"Max persisted ledger is " << maxDisallowedLedger_;
2096 std::move(config), std::move(logs), std::move(timeKeeper));
2102 for (
auto const& [name, ep] : endpoints)
2104 if (!config.
exists(name))
2107 auto& section = config[name];
2108 auto const optPort = section.get(
"port");
2111 std::uint16_t const port = beast::lexicalCast<std::uint16_t>(*optPort);
boost::asio::io_context & get_io_context()
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_context 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
beast::io_latency_probe< std::chrono::steady_clock > m_probe
void operator()(Duration const &elapsed)
std::atomic< std::chrono::milliseconds > lastSample_
io_latency_sampler(beast::insight::Event ev, beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context &ios)
std::chrono::milliseconds get() const
LedgerReplayer & getLedgerReplayer() override
Application::MutexType & getMasterMutex() override
std::optional< std::pair< PublicKey, SecretKey > > nodeIdentity_
InboundLedgers & getInboundLedgers() override
NodeCache m_tempNodeCache
std::unique_ptr< LedgerCleaner > ledgerCleaner_
std::unique_ptr< LoadManager > m_loadManager
void start(bool withTimers) override
LoadFeeTrack & getFeeTrack() override
Cluster & cluster() override
std::unique_ptr< perf::PerfLog > perfLog_
std::unique_ptr< HashRouter > hashRouter_
std::optional< OpenLedger > openLedger_
RCLValidations & getValidations() override
OpenLedger & openLedger() override
Resource::Manager & getResourceManager() override
NodeStoreScheduler m_nodeStoreScheduler
ClosureCounter< void, boost::system::error_code const & > waitHandlerCounter_
RelationalDatabase & getRelationalDatabase() override
TransactionMaster & getMasterTransaction() override
std::chrono::milliseconds getIOLatency() override
std::unique_ptr< CollectorManager > m_collectorManager
boost::asio::io_context & getIOContext() override
std::optional< PublicKey const > getValidationPublicKey() const override
HashRouter & getHashRouter() override
LoadManager & getLoadManager() override
PendingSaves pendingSaves_
std::atomic< bool > checkSigs_
bool checkSigs() const override
bool serverOkay(std::string &reason) override
std::unique_ptr< SHAMapStore > m_shaMapStore
Application::MutexType m_masterMutex
InboundTransactions & getInboundTransactions() override
io_latency_sampler m_io_latency_sampler
std::unique_ptr< AmendmentTable > m_amendmentTable
std::unique_ptr< InboundTransactions > m_inboundTransactions
SHAMapStore & getSHAMapStore() override
boost::asio::steady_timer sweepTimer_
std::unique_ptr< NodeStore::Database > m_nodeStore
std::unique_ptr< LoadFeeTrack > mFeeTrack
boost::asio::steady_timer entropyTimer_
std::unique_ptr< Overlay > overlay_
bool setup(boost::program_options::variables_map const &cmdline) override
bool initRelationalDatabase()
Overlay & overlay() override
std::unique_ptr< Config > config_
ManifestCache & publisherManifests() override
std::unique_ptr< ManifestCache > validatorManifests_
CollectorManager & getCollectorManager() override
std::optional< uint256 > trapTxID_
std::unique_ptr< ResolverAsio > m_resolver
NetworkOPs & getOPs() override
TimeKeeper & timeKeeper() override
std::unique_ptr< ValidatorList > validators_
std::unique_ptr< TxQ > txQ_
static std::size_t numberOfThreads(Config const &config)
OpenLedger const & openLedger() const override
std::unique_ptr< ManifestCache > publisherManifests_
LedgerIndex getMaxDisallowedLedger() override
Ensure that a newly-started validator does not sign proposals older than the last ledger it persisted...
NodeCache & getTempNodeCache() override
Application & app() override
ValidatorList & validators() override
PeerReservationTable & peerReservations() override
ApplicationImp(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
std::unique_ptr< PeerReservationTable > peerReservations_
std::unique_ptr< Resource::Manager > m_resourceManager
std::pair< PublicKey, SecretKey > const & nodeIdentity() override
std::unique_ptr< Logs > logs_
std::unique_ptr< DatabaseCon > mWalletDB
CachedSLEs & cachedSLEs() override
NetworkIDService & getNetworkIDService() override
ValidatorSite & validatorSites() override
virtual std::optional< uint256 > const & trapTxID() const override
std::atomic_flag isTimeToStop
std::optional< SQLiteDatabase > relationalDatabase_
std::unique_ptr< LedgerMaster > m_ledgerMaster
std::unique_ptr< GRPCServer > grpcServer_
std::unique_ptr< ServerHandler > serverHandler_
ValidatorKeys const validatorKeys_
std::uint64_t instanceID() const override
Returns a 64-bit instance identifier, generated at startup.
OrderBookDB & getOrderBookDB() override
Family & getNodeFamily() override
void gotTXSet(std::shared_ptr< SHAMap > const &set, bool fromAcquire)
Config & config() override
DatabaseCon & getWalletDB() override
Retrieve the "wallet database".
PathRequests & getPathRequests() override
bool isStopping() const override
std::unique_ptr< TimeKeeper > timeKeeper_
beast::Journal journal(std::string const &name) override
std::unique_ptr< ValidatorSite > validatorSites_
RCLValidations mValidations
void signalStop(std::string msg) override
std::uint64_t const instanceCookie_
LedgerCleaner & getLedgerCleaner() override
ManifestCache & validatorManifests() override
AmendmentTable & getAmendmentTable() override
int fdRequired() const override
TaggedCache< uint256, AcceptedLedger > m_acceptedLedgerCache
std::unique_ptr< PathRequests > m_pathRequests
std::unique_ptr< JobQueue > m_jobQueue
LedgerMaster & getLedgerMaster() override
NodeStore::Database & getNodeStore() override
std::unique_ptr< OrderBookDB > m_orderBookDB
TransactionMaster m_txMaster
std::unique_ptr< Cluster > cluster_
std::unique_ptr< NetworkOPs > m_networkOPs
virtual ServerHandler & getServerHandler() override
JobQueue & getJobQueue() override
PendingSaves & pendingSaves() override
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
std::unique_ptr< InboundLedgers > m_inboundLedgers
TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache() override
perf::PerfLog & getPerfLog() override
std::unique_ptr< NetworkIDService > networkIDService_
boost::asio::signal_set m_signals
std::unique_ptr< LedgerReplayer > m_ledgerReplayer
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.
Service that provides access to the network ID.
Provides server functionality for clients.
A NodeStore::Scheduler which uses the JobQueue.
Persistency layer for NodeObject.
Simple NodeStore Scheduler that just performs the tasks synchronously.
static Manager & instance()
Returns the instance of the manager singleton.
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.
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.
Tracks order books in the ledger.
Manages the set of connected peers.
Keeps track of which ledgers haven't been fully saved.
static std::unique_ptr< ResolverAsio > New(boost::asio::io_context &, 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::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
std::unique_ptr< LedgerCleaner > make_LedgerCleaner(Application &app, beast::Journal journal)
std::unique_ptr< LoadManager > make_LoadManager(Application &app, beast::Journal journal)
Stopwatch & stopwatch()
Returns an instance of a wall clock.
TxQ::Setup setup_TxQ(Config const &config)
Build a TxQ::Setup object from application configuration.
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
create_genesis_t const create_genesis
HashRouter::Setup setup_HashRouter(Config const &config)
Create HashRouter setup from configuration.
std::pair< PublicKey, SecretKey > getNodeIdentity(soci::session &session)
Returns a stable public and private key for this node.
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
std::unique_ptr< SHAMapStore > make_SHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
std::unique_ptr< AmendmentTable > make_AmendmentTable(ServiceRegistry ®istry, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
std::unique_ptr< NetworkOPs > make_NetworkOPs(ServiceRegistry ®istry, NetworkOPs::clock_type &clock, bool standalone, std::size_t minPeerCount, bool start_valid, JobQueue &job_queue, LedgerMaster &ledgerMaster, ValidatorKeys const &validatorKeys, boost::asio::io_context &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
std::unique_ptr< CollectorManager > make_CollectorManager(Section const ¶ms, beast::Journal journal)
std::unique_ptr< InboundLedgers > make_InboundLedgers(Application &app, InboundLedgers::clock_type &clock, beast::insight::Collector::ptr const &collector)
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_context &io_context, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
constexpr auto megabytes(T value) noexcept
static void fixConfigPorts(Config &config, Endpoints const &endpoints)
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
void addJson(Json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a Json::Value with a description of the ledger.
Overlay::Setup setup_Overlay(BasicConfig const &config)
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
std::unordered_map< std::string, boost::asio::ip::tcp::endpoint > Endpoints
std::optional< uint256 > getRegisteredFeature(std::string const &name)
std::unique_ptr< OrderBookDB > make_OrderBookDB(ServiceRegistry ®istry, OrderBookDBConfig const &config)
Create an OrderBookDB instance.
SQLiteDatabase setup_RelationalDatabase(ServiceRegistry ®istry, Config const &config, JobQueue &jobQueue)
setup_RelationalDatabase Creates and returns a SQLiteDatabase instance based on configuration.
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
std::unique_ptr< Overlay > make_Overlay(Application &app, Overlay::Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_context &io_context, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
Creates the implementation of Overlay.
static std::string importNodeDatabase()