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/OrderBookDB.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/DBInit.h>
15#include <xrpld/app/main/GRPCServer.h>
16#include <xrpld/app/main/LoadManager.h>
17#include <xrpld/app/main/NodeIdentity.h>
18#include <xrpld/app/main/NodeStoreScheduler.h>
19#include <xrpld/app/misc/AmendmentTable.h>
20#include <xrpld/app/misc/HashRouter.h>
21#include <xrpld/app/misc/LoadFeeTrack.h>
22#include <xrpld/app/misc/NetworkOPs.h>
23#include <xrpld/app/misc/SHAMapStore.h>
24#include <xrpld/app/misc/TxQ.h>
25#include <xrpld/app/misc/ValidatorKeys.h>
26#include <xrpld/app/misc/ValidatorSite.h>
27#include <xrpld/app/paths/PathRequests.h>
28#include <xrpld/app/rdb/RelationalDatabase.h>
29#include <xrpld/app/rdb/Wallet.h>
30#include <xrpld/app/tx/apply.h>
31#include <xrpld/core/DatabaseCon.h>
32#include <xrpld/overlay/Cluster.h>
33#include <xrpld/overlay/PeerReservationTable.h>
34#include <xrpld/overlay/PeerSet.h>
35#include <xrpld/overlay/make_Overlay.h>
36#include <xrpld/perflog/PerfLog.h>
37#include <xrpld/shamap/NodeFamily.h>
39#include <xrpl/basics/ByteUtilities.h>
40#include <xrpl/basics/ResolverAsio.h>
41#include <xrpl/basics/random.h>
42#include <xrpl/beast/asio/io_latency_probe.h>
43#include <xrpl/beast/core/LexicalCast.h>
44#include <xrpl/crypto/csprng.h>
45#include <xrpl/json/json_reader.h>
46#include <xrpl/nodestore/DummyScheduler.h>
47#include <xrpl/protocol/ApiVersion.h>
48#include <xrpl/protocol/BuildInfo.h>
49#include <xrpl/protocol/Feature.h>
50#include <xrpl/protocol/Protocol.h>
51#include <xrpl/protocol/STParsedJSON.h>
52#include <xrpl/resource/Fees.h>
54#include <boost/algorithm/string/predicate.hpp>
55#include <boost/asio/steady_timer.hpp>
56#include <boost/system/error_code.hpp>
91 boost::asio::io_context& ios)
105 template <
class Duration>
110 auto const lastSample = ceil<milliseconds>(elapsed);
114 if (lastSample >= 10ms)
116 if (lastSample >= 500ms)
119 <<
"io_context latency = " << lastSample.count();
225#if XRPL_SINGLE_IO_SERVICE_THREAD
273 config_->section(SECTION_INSIGHT),
274 logs_->journal(
"Collector")))
300 logs_->journal(
"JobQueue"),
309 logs_->journal(
"SHAMapStore")))
316 logs_->journal(
"TaggedCache"))
323 logs_->journal(
"CachedSLEs"))
329 logs_->journal(
"Resource")))
377 logs_->journal(
"TaggedCache"))
389 logs_->journal(
"NetworkOPs"),
395 logs_->journal(
"PeerReservationTable")))
407 config_->legacy(
"database_path"),
408 logs_->journal(
"ValidatorList"),
432 logs_->journal(
"Validations"))
452 logs_->journal(
"Application"),
482 setup(boost::program_options::variables_map
const& cmdline)
override;
484 start(
bool withTimers)
override;
549 "Accessing Application::nodeIdentity() before it is initialized.");
572 "ripple::ApplicationImp::getServerHandler : non-null server "
577 boost::asio::io_context&
780 overlay_,
"ripple::ApplicationImp::overlay : non-null overlay");
789 "ripple::ApplicationImp::getTxQ : non-null transaction queue");
798 "ripple::ApplicationImp::getRelationalDatabase : non-null "
799 "relational database");
808 "ripple::ApplicationImp::getWalletDB : non-null wallet database");
825 "ripple::ApplicationImp::initRelationalDatabase : null wallet "
835 setup.useGlobalPragma =
false;
842 <<
"Failed to initialize SQL databases: " << e.
what();
854 auto j =
logs_->journal(
"NodeObject");
865 JLOG(j.warn()) <<
"Starting node import from '" << source->getName()
869 auto const start = steady_clock::now();
874 duration_cast<seconds>(steady_clock::now() -
start);
875 JLOG(j.warn()) <<
"Node import from '" << source->getName()
876 <<
"' took " << elapsed.count() <<
" seconds.";
899 [
this](boost::system::error_code
const& e) {
900 if (e.value() == boost::system::errc::success)
903 jtSWEEP,
"sweep", [this]() { doSweep(); });
906 if (e.value() != boost::system::errc::success &&
907 e.value() != boost::asio::error::operation_aborted)
910 JLOG(m_journal.error())
911 <<
"Sweep timer got error '" << e.message()
912 <<
"'. Restarting timer.";
920 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
928 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
929 [
this](boost::system::error_code
const& e) {
930 if (e.value() == boost::system::errc::success)
932 crypto_prng().mix_entropy();
936 if (e.value() != boost::system::errc::success &&
937 e.value() != boost::asio::error::operation_aborted)
940 JLOG(m_journal.error())
941 <<
"Entropy timer got error '" << e.message()
942 <<
"'. Restarting timer.";
947 using namespace std::chrono_literals;
948 entropyTimer_.expires_after(5min);
949 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
956 if (!config_->standalone() &&
957 !getRelationalDatabase().transactionDbHasSpace(*config_))
959 signalStop(
"Out of transaction DB space");
968 nodeFamily_.getFullBelowCache();
971 nodeFamily_.getTreeNodeCache();
973 std::size_t const oldFullBelowSize = fullBelowCache->size();
974 std::size_t const oldTreeNodeSize = treeNodeCache->size();
978 JLOG(m_journal.debug())
979 <<
"NodeFamily::FullBelowCache sweep. Size before: "
981 <<
"; size after: " << fullBelowCache->size();
983 JLOG(m_journal.debug())
984 <<
"NodeFamily::TreeNodeCache sweep. Size before: "
985 << oldTreeNodeSize <<
"; size after: " << treeNodeCache->size();
989 getMasterTransaction().getCache();
993 getMasterTransaction().sweep();
995 JLOG(m_journal.debug())
996 <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
997 <<
"; size after: " << masterTxCache.
size();
1001 getNodeStore().sweep();
1005 getLedgerMaster().getFetchPackCacheSize();
1007 getLedgerMaster().sweep();
1009 JLOG(m_journal.debug())
1010 <<
"LedgerMaster sweep. Size before: "
1011 << oldLedgerMasterCacheSize <<
"; size after: "
1012 << getLedgerMaster().getFetchPackCacheSize();
1016 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1018 getTempNodeCache().sweep();
1020 JLOG(m_journal.debug())
1021 <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1022 <<
"; size after: " << getTempNodeCache().size();
1026 getValidations().sizeOfCurrentCache();
1028 getValidations().sizeOfSeqEnforcersCache();
1030 getValidations().sizeOfByLedgerCache();
1032 getValidations().sizeOfBySequenceCache();
1034 getValidations().expire(m_journal);
1036 JLOG(m_journal.debug())
1037 <<
"Validations Current expire. Size before: "
1038 << oldCurrentCacheSize
1039 <<
"; size after: " << getValidations().sizeOfCurrentCache();
1041 JLOG(m_journal.debug())
1042 <<
"Validations SeqEnforcer expire. Size before: "
1043 << oldSizeSeqEnforcesSize <<
"; size after: "
1044 << getValidations().sizeOfSeqEnforcersCache();
1046 JLOG(m_journal.debug())
1047 <<
"Validations ByLedger expire. Size before: "
1049 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1051 JLOG(m_journal.debug())
1052 <<
"Validations BySequence expire. Size before: "
1053 << oldBySequenceSize
1054 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1058 getInboundLedgers().cacheSize();
1060 getInboundLedgers().sweep();
1062 JLOG(m_journal.debug())
1063 <<
"InboundLedgers sweep. Size before: "
1064 << oldInboundLedgersSize
1065 <<
"; size after: " << getInboundLedgers().cacheSize();
1068 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1069 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1070 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1072 getLedgerReplayer().sweep();
1074 JLOG(m_journal.debug())
1075 <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1076 <<
"; size after: " << getLedgerReplayer().tasksSize();
1078 JLOG(m_journal.debug())
1079 <<
"LedgerReplayer deltas sweep. Size before: "
1081 <<
"; size after: " << getLedgerReplayer().deltasSize();
1083 JLOG(m_journal.debug())
1084 <<
"LedgerReplayer skipLists sweep. Size before: "
1086 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1090 m_acceptedLedgerCache.size();
1092 m_acceptedLedgerCache.sweep();
1094 JLOG(m_journal.debug())
1095 <<
"AcceptedLedgerCache sweep. Size before: "
1096 << oldAcceptedLedgerSize
1097 <<
"; size after: " << m_acceptedLedgerCache.size();
1100 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1102 cachedSLEs_.sweep();
1104 JLOG(m_journal.debug())
1105 <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1106 <<
"; size after: " << cachedSLEs_.size();
1116 return maxDisallowedLedger_;
1131 startGenesisLedger();
1134 getLastFullLedger();
1147 setMaxDisallowedLedger();
1154ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1164 m_signals.add(SIGINT);
1165 m_signals.add(SIGTERM);
1166 m_signals.async_wait(
1167 [
this](boost::system::error_code
const& ec,
int signum) {
1169 if (ec == boost::asio::error::operation_aborted)
1172 JLOG(m_journal.info()) <<
"Received signal " << signum;
1174 if (signum == SIGTERM || signum == SIGINT)
1175 signalStop(
"Signal: " + to_string(signum));
1178 auto debug_log = config_->getDebugLogFile();
1180 if (!debug_log.empty())
1185 if (!logs_->open(debug_log))
1186 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1189 if (logs_->threshold() > kDebug)
1190 logs_->threshold(kDebug);
1193 JLOG(m_journal.info()) <<
"Process starting: "
1194 << BuildInfo::getFullVersionString()
1195 <<
", Instance Cookie: " << instanceCookie_;
1197 if (numberOfThreads(*config_) < 2)
1199 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1200 "system configuration.";
1204 logs_->silent(config_->silent());
1206 if (!initRelationalDatabase() || !initNodeStore())
1209 if (!peerReservations_->load(getWalletDB()))
1211 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1215 if (validatorKeys_.keys)
1216 setMaxDisallowedLedger();
1220 auto const supported = []() {
1221 auto const& amendments = detail::supportedAmendments();
1223 supported.reserve(amendments.size());
1224 for (
auto const& [a, vote] : amendments)
1228 f,
"ripple::ApplicationImp::setup : registered feature");
1230 supported.emplace_back(a, *f, vote);
1234 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1236 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1240 config().AMENDMENT_MAJORITY_TIME,
1244 logs_->journal(
"Amendments"));
1247 Pathfinder::initPathTable();
1249 auto const startUp = config_->START_UP;
1250 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1251 if (startUp == Config::FRESH)
1253 JLOG(m_journal.info()) <<
"Starting new Ledger";
1255 startGenesisLedger();
1258 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1259 startUp == Config::REPLAY)
1261 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1264 config_->START_LEDGER,
1265 startUp == Config::REPLAY,
1266 startUp == Config::LOAD_FILE,
1267 config_->TRAP_TX_HASH))
1269 JLOG(m_journal.error())
1270 <<
"The specified ledger could not be loaded.";
1271 if (config_->FAST_LOAD)
1275 startGenesisLedger();
1283 else if (startUp == Config::NETWORK)
1287 if (!config_->standalone())
1288 m_networkOPs->setNeedNetworkLedger();
1290 startGenesisLedger();
1294 startGenesisLedger();
1297 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1299 m_ledgerMaster->setLedgerRangePresent(
1300 forcedRange->first, forcedRange->second);
1303 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1307 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1309 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1314 if (validatorKeys_.configInvalid())
1317 if (!validatorManifests_->load(
1319 "ValidatorManifests",
1320 validatorKeys_.manifest,
1321 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1323 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1327 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1336 if (validatorKeys_.keys)
1337 localSigningKey = validatorKeys_.keys->publicKey;
1340 if (!validators_->load(
1342 config().section(SECTION_VALIDATORS).values(),
1343 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1344 config().VALIDATOR_LIST_THRESHOLD))
1346 JLOG(m_journal.fatal())
1347 <<
"Invalid entry in validator configuration.";
1352 if (!validatorSites_->load(
1353 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1355 JLOG(m_journal.fatal())
1356 <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1361 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1382 m_collectorManager->collector());
1386 if (!m_networkOPs->beginConsensus(
1387 m_ledgerMaster->getClosedLedger()->info().hash, {}))
1389 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1399 serverHandler_->setup(setup, m_journal);
1404 if (
auto stream = m_journal.fatal())
1406 stream <<
"Unable to setup server handler";
1408 stream <<
": " << e.
what();
1415 if (!config_->standalone())
1419 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1421 JLOG(m_journal.warn())
1422 <<
"No outbound peer connections will be made";
1427 m_networkOPs->setStateTimer();
1431 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1433 m_networkOPs->setStandAlone();
1436 if (config_->canSign())
1438 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1439 "'sign' and 'sign_for'";
1440 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1441 "implications and have";
1442 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1443 "in a future release of";
1444 JLOG(m_journal.warn()) <<
"*** rippled.";
1445 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1446 "transactions please edit your";
1447 JLOG(m_journal.warn())
1448 <<
"*** configuration file and remove the [enable_signing] stanza.";
1449 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1450 "please migrate to a";
1451 JLOG(m_journal.warn())
1452 <<
"*** standalone signing solution as soon as possible.";
1458 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1463 if (!jrReader.
parse(cmd, jvCommand))
1465 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in ["
1466 << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1469 if (!config_->quiet())
1471 JLOG(m_journal.fatal())
1472 <<
"Startup RPC: " << jvCommand <<
std::endl;
1478 {journal(
"RPCHandler"),
1487 RPC::apiMaximumSupportedVersion},
1491 RPC::doCommand(context, jvResult);
1493 if (!config_->quiet())
1495 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1499 validatorSites_->start();
1505ApplicationImp::start(
bool withTimers)
1507 JLOG(m_journal.info()) <<
"Application starting. Version is "
1508 << BuildInfo::getVersionString();
1516 m_io_latency_sampler.start();
1517 m_resolver->start();
1518 m_loadManager->start();
1519 m_shaMapStore->start();
1523 if (grpcServer_->start())
1525 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1527 ledgerCleaner_->start();
1532ApplicationImp::run()
1534 if (!config_->standalone())
1540 getLoadManager().activateStallDetector();
1545 stoppingCondition_.wait(lk, [
this] {
return isTimeToStop.load(); });
1548 JLOG(m_journal.debug()) <<
"Application stopping";
1550 m_io_latency_sampler.cancel_async();
1558 m_io_latency_sampler.cancel();
1560 m_resolver->stop_async();
1570 sweepTimer_.cancel();
1572 catch (boost::system::system_error
const& e)
1574 JLOG(m_journal.error())
1575 <<
"Application: sweepTimer cancel error: " << e.what();
1580 entropyTimer_.cancel();
1582 catch (boost::system::system_error
const& e)
1584 JLOG(m_journal.error())
1585 <<
"Application: entropyTimer cancel error: " << e.what();
1591 using namespace std::chrono_literals;
1593 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1595 mValidations.flush();
1597 validatorSites_->stop();
1600 validatorManifests_->save(
1601 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1602 return validators().listed(pubKey);
1605 publisherManifests_->save(
1606 getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1607 return validators().trustedPublisher(pubKey);
1612 m_loadManager->stop();
1613 m_shaMapStore->stop();
1617 grpcServer_->stop();
1618 m_networkOPs->stop();
1619 serverHandler_->stop();
1620 m_ledgerReplayer->stop();
1621 m_inboundTransactions->stop();
1622 m_inboundLedgers->stop();
1623 ledgerCleaner_->stop();
1624 m_nodeStore->stop();
1627 JLOG(m_journal.info()) <<
"Done.";
1633 if (!isTimeToStop.exchange(
true))
1636 JLOG(m_journal.warn()) <<
"Server stopping";
1638 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1640 stoppingCondition_.notify_all();
1645ApplicationImp::checkSigs()
const
1651ApplicationImp::checkSigs(
bool check)
1657ApplicationImp::isStopping()
const
1659 return isTimeToStop.load();
1663ApplicationImp::fdRequired()
const
1670 needed += 2 * overlay_->limit();
1674 needed +=
std::max(5, m_shaMapStore->fdRequired());
1678 for (
auto const& p : serverHandler_->setup().ports)
1688ApplicationImp::startGenesisLedger()
1691 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1696 m_ledgerMaster->storeLedger(genesis);
1700 next->updateSkipList();
1702 next->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1703 next->read(keylet::fees()),
1704 "ripple::ApplicationImp::startGenesisLedger : valid ledger fees");
1705 next->setImmutable();
1706 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1707 m_ledgerMaster->storeLedger(next);
1708 m_ledgerMaster->switchLCL(next);
1712ApplicationImp::getLastFullLedger()
1714 auto j = journal(
"Ledger");
1724 ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1725 ledger->read(keylet::fees()),
1726 "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
1727 ledger->setImmutable();
1729 if (getLedgerMaster().haveLedger(seq))
1730 ledger->setValidated();
1732 if (ledger->info().hash ==
hash)
1734 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1738 if (
auto stream = j.error())
1740 stream <<
"Failed on ledger";
1742 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1750 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1764 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1771 if (!reader.
parse(ledgerFile, jLedger))
1773 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1780 if (ledger.
get().isMember(
"result"))
1781 ledger = ledger.
get()[
"result"];
1783 if (ledger.
get().isMember(
"ledger"))
1784 ledger = ledger.
get()[
"ledger"];
1787 auto closeTime = timeKeeper().closeTime();
1788 using namespace std::chrono_literals;
1789 auto closeTimeResolution = 30s;
1790 bool closeTimeEstimated =
false;
1793 if (ledger.
get().isMember(
"accountState"))
1795 if (ledger.
get().isMember(jss::ledger_index))
1797 seq = ledger.
get()[jss::ledger_index].asUInt();
1800 if (ledger.
get().isMember(
"close_time"))
1803 using d = tp::duration;
1804 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1806 if (ledger.
get().isMember(
"close_time_resolution"))
1809 closeTimeResolution =
1810 seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1812 if (ledger.
get().isMember(
"close_time_estimated"))
1814 closeTimeEstimated =
1815 ledger.
get()[
"close_time_estimated"].asBool();
1817 if (ledger.
get().isMember(
"total_coins"))
1819 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1820 ledger.
get()[
"total_coins"].asString());
1823 ledger = ledger.
get()[
"accountState"];
1826 if (!ledger.
get().isArrayOrNull())
1828 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1834 loadLedger->setTotalDrops(totalDrops);
1836 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1842 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1850 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1860 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1868 if (!loadLedger->addSLE(sle))
1870 JLOG(m_journal.fatal())
1871 <<
"Couldn't add serialized ledger: " << uIndex;
1879 loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
1880 loadLedger->read(keylet::fees()),
1881 "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1882 loadLedger->setAccepted(
1883 closeTime, closeTimeResolution, !closeTimeEstimated);
1889 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1895ApplicationImp::loadOldLedger(
1907 if (!ledgerID.
empty())
1908 loadLedger = loadLedgerFromFile(ledgerID);
1910 else if (ledgerID.
length() == 64)
1914 if (
hash.parseHex(ledgerID))
1925 InboundLedger::Reason::GENERIC,
1928 if (il->checkLocal())
1929 loadLedger = il->getLedger();
1933 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1935 loadLedger = getLastFullLedger();
1954 replayLedger = loadLedger;
1956 JLOG(m_journal.info()) <<
"Loading parent ledger";
1958 loadLedger =
loadByHash(replayLedger->info().parentHash, *
this);
1961 JLOG(m_journal.info())
1962 <<
"Loading parent ledger from node store";
1967 replayLedger->info().parentHash,
1969 InboundLedger::Reason::GENERIC,
1973 if (il->checkLocal())
1974 loadLedger = il->getLedger();
1979 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1981 "ripple::ApplicationImp::loadOldLedger : replay ledger "
1988 using namespace std::chrono_literals;
1989 using namespace date;
1992 if (loadLedger->info().closeTime < ledgerWarnTimePoint)
1994 JLOG(m_journal.fatal())
1995 <<
"\n\n*** WARNING ***\n"
1996 "You are replaying a ledger from before "
1997 << to_string(ledgerWarnTimePoint)
1999 "This replay will not handle your ledger as it was "
2001 "handled.\nConsider running an earlier version of rippled "
2003 "get the older rules.\n*** CONTINUING ***\n";
2006 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->info().hash
2007 <<
" seq:" << loadLedger->info().seq;
2009 if (loadLedger->info().accountHash.isZero())
2012 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
2014 "ripple::ApplicationImp::loadOldLedger : ledger is empty");
2019 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
2022 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
2024 "ripple::ApplicationImp::loadOldLedger : ledger is missing "
2030 if (!loadLedger->assertSensible(journal(
"Ledger")))
2033 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
2035 "ripple::ApplicationImp::loadOldLedger : ledger is not "
2041 m_ledgerMaster->setLedgerRangePresent(
2042 loadLedger->info().seq, loadLedger->info().seq);
2044 m_ledgerMaster->switchLCL(loadLedger);
2045 loadLedger->setValidated();
2046 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
2047 openLedger_.emplace(
2048 loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
2057 for (
auto const& [_, tx] : replayData->orderedTxns())
2060 auto txID = tx->getTransactionID();
2061 if (trapTxID == txID)
2064 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
2070 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2072 openLedger_->modify(
2079 m_ledgerMaster->takeReplay(std::move(replayData));
2081 if (trapTxID && !trapTxID_)
2083 JLOG(m_journal.fatal())
2084 <<
"Ledger " << replayLedger->info().seq
2085 <<
" does not contain the transaction hash " << *trapTxID;
2092 JLOG(m_journal.fatal())
2093 <<
"While loading specified ledger: " << mn.
what();
2096 catch (boost::bad_lexical_cast&)
2098 JLOG(m_journal.fatal())
2099 <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2109 if (!config().ELB_SUPPORT)
2114 reason =
"Server is shutting down";
2118 if (getOPs().isNeedNetworkLedger())
2120 reason =
"Not synchronized with network yet";
2124 if (getOPs().isAmendmentBlocked())
2126 reason =
"Server version too old";
2130 if (getOPs().isUNLBlocked())
2132 reason =
"No valid validator list available";
2136 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2138 reason =
"Not synchronized with network";
2142 if (!getLedgerMaster().isCaughtUp(reason))
2145 if (getFeeTrack().isLoadedLocal())
2147 reason =
"Too much load";
2157 return logs_->journal(name);
2161ApplicationImp::setMaxDisallowedLedger()
2163 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2165 maxDisallowedLedger_ = *seq;
2167 JLOG(m_journal.trace())
2168 <<
"Max persisted ledger is " << maxDisallowedLedger_;
2186 std::move(config), std::move(logs), std::move(timeKeeper));
2192 for (
auto const& [name, ep] : endpoints)
2194 if (!config.
exists(name))
2197 auto& section = config[name];
2198 auto const optPort = section.get(
"port");
2202 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
io_latency_sampler(beast::insight::Event ev, beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context &ios)
std::atomic< std::chrono::milliseconds > lastSample_
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
boost::asio::io_context & getIOContext() 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
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_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::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
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_context &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
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)
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
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.
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_context &io_context, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
create_genesis_t const create_genesis
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 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< SHAMapStore > make_SHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
static std::string importNodeDatabase()