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/shamap/NodeFamily.h>
38#include <xrpl/basics/ByteUtilities.h>
39#include <xrpl/basics/ResolverAsio.h>
40#include <xrpl/basics/random.h>
41#include <xrpl/beast/asio/io_latency_probe.h>
42#include <xrpl/beast/core/LexicalCast.h>
43#include <xrpl/core/PerfLog.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 "xrpl::ApplicationImp::getServerHandler : non-null server "
577 boost::asio::io_context&
780 overlay_,
"xrpl::ApplicationImp::overlay : non-null overlay");
788 txQ_,
"xrpl::ApplicationImp::getTxQ : non-null transaction queue");
797 "xrpl::ApplicationImp::getRelationalDatabase : non-null "
798 "relational database");
807 "xrpl::ApplicationImp::getWalletDB : non-null wallet database");
824 "xrpl::ApplicationImp::initRelationalDatabase : null wallet "
834 setup.useGlobalPragma =
false;
841 <<
"Failed to initialize SQL databases: " << e.
what();
853 auto j =
logs_->journal(
"NodeObject");
864 JLOG(j.warn()) <<
"Starting node import from '" << source->getName()
868 auto const start = steady_clock::now();
873 duration_cast<seconds>(steady_clock::now() -
start);
874 JLOG(j.warn()) <<
"Node import from '" << source->getName()
875 <<
"' took " << elapsed.count() <<
" seconds.";
898 [
this](boost::system::error_code
const& e) {
899 if (e.value() == boost::system::errc::success)
902 jtSWEEP,
"sweep", [this]() { doSweep(); });
905 if (e.value() != boost::system::errc::success &&
906 e.value() != boost::asio::error::operation_aborted)
909 JLOG(m_journal.error())
910 <<
"Sweep timer got error '" << e.message()
911 <<
"'. Restarting timer.";
919 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
927 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
928 [
this](boost::system::error_code
const& e) {
929 if (e.value() == boost::system::errc::success)
931 crypto_prng().mix_entropy();
935 if (e.value() != boost::system::errc::success &&
936 e.value() != boost::asio::error::operation_aborted)
939 JLOG(m_journal.error())
940 <<
"Entropy timer got error '" << e.message()
941 <<
"'. Restarting timer.";
946 using namespace std::chrono_literals;
947 entropyTimer_.expires_after(5min);
948 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
955 if (!config_->standalone() &&
956 !getRelationalDatabase().transactionDbHasSpace(*config_))
958 signalStop(
"Out of transaction DB space");
967 nodeFamily_.getFullBelowCache();
970 nodeFamily_.getTreeNodeCache();
972 std::size_t const oldFullBelowSize = fullBelowCache->size();
973 std::size_t const oldTreeNodeSize = treeNodeCache->size();
977 JLOG(m_journal.debug())
978 <<
"NodeFamily::FullBelowCache sweep. Size before: "
980 <<
"; size after: " << fullBelowCache->size();
982 JLOG(m_journal.debug())
983 <<
"NodeFamily::TreeNodeCache sweep. Size before: "
984 << oldTreeNodeSize <<
"; size after: " << treeNodeCache->size();
988 getMasterTransaction().getCache();
992 getMasterTransaction().sweep();
994 JLOG(m_journal.debug())
995 <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
996 <<
"; size after: " << masterTxCache.
size();
1000 getNodeStore().sweep();
1004 getLedgerMaster().getFetchPackCacheSize();
1006 getLedgerMaster().sweep();
1008 JLOG(m_journal.debug())
1009 <<
"LedgerMaster sweep. Size before: "
1010 << oldLedgerMasterCacheSize <<
"; size after: "
1011 << getLedgerMaster().getFetchPackCacheSize();
1015 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1017 getTempNodeCache().sweep();
1019 JLOG(m_journal.debug())
1020 <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1021 <<
"; size after: " << getTempNodeCache().size();
1025 getValidations().sizeOfCurrentCache();
1027 getValidations().sizeOfSeqEnforcersCache();
1029 getValidations().sizeOfByLedgerCache();
1031 getValidations().sizeOfBySequenceCache();
1033 getValidations().expire(m_journal);
1035 JLOG(m_journal.debug())
1036 <<
"Validations Current expire. Size before: "
1037 << oldCurrentCacheSize
1038 <<
"; size after: " << getValidations().sizeOfCurrentCache();
1040 JLOG(m_journal.debug())
1041 <<
"Validations SeqEnforcer expire. Size before: "
1042 << oldSizeSeqEnforcesSize <<
"; size after: "
1043 << getValidations().sizeOfSeqEnforcersCache();
1045 JLOG(m_journal.debug())
1046 <<
"Validations ByLedger expire. Size before: "
1048 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1050 JLOG(m_journal.debug())
1051 <<
"Validations BySequence expire. Size before: "
1052 << oldBySequenceSize
1053 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1057 getInboundLedgers().cacheSize();
1059 getInboundLedgers().sweep();
1061 JLOG(m_journal.debug())
1062 <<
"InboundLedgers sweep. Size before: "
1063 << oldInboundLedgersSize
1064 <<
"; size after: " << getInboundLedgers().cacheSize();
1067 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1068 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1069 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1071 getLedgerReplayer().sweep();
1073 JLOG(m_journal.debug())
1074 <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1075 <<
"; size after: " << getLedgerReplayer().tasksSize();
1077 JLOG(m_journal.debug())
1078 <<
"LedgerReplayer deltas sweep. Size before: "
1080 <<
"; size after: " << getLedgerReplayer().deltasSize();
1082 JLOG(m_journal.debug())
1083 <<
"LedgerReplayer skipLists sweep. Size before: "
1085 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1089 m_acceptedLedgerCache.size();
1091 m_acceptedLedgerCache.sweep();
1093 JLOG(m_journal.debug())
1094 <<
"AcceptedLedgerCache sweep. Size before: "
1095 << oldAcceptedLedgerSize
1096 <<
"; size after: " << m_acceptedLedgerCache.size();
1099 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1101 cachedSLEs_.sweep();
1103 JLOG(m_journal.debug())
1104 <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1105 <<
"; size after: " << cachedSLEs_.size();
1115 return maxDisallowedLedger_;
1130 startGenesisLedger();
1133 getLastFullLedger();
1146 setMaxDisallowedLedger();
1153ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1163 m_signals.add(SIGINT);
1164 m_signals.add(SIGTERM);
1165 m_signals.async_wait(
1166 [
this](boost::system::error_code
const& ec,
int signum) {
1168 if (ec == boost::asio::error::operation_aborted)
1171 JLOG(m_journal.info()) <<
"Received signal " << signum;
1173 if (signum == SIGTERM || signum == SIGINT)
1174 signalStop(
"Signal: " + to_string(signum));
1177 auto debug_log = config_->getDebugLogFile();
1179 if (!debug_log.empty())
1184 if (!logs_->open(debug_log))
1185 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1188 if (logs_->threshold() > kDebug)
1189 logs_->threshold(kDebug);
1192 JLOG(m_journal.info()) <<
"Process starting: "
1193 << BuildInfo::getFullVersionString()
1194 <<
", Instance Cookie: " << instanceCookie_;
1196 if (numberOfThreads(*config_) < 2)
1198 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1199 "system configuration.";
1203 logs_->silent(config_->silent());
1205 if (!initRelationalDatabase() || !initNodeStore())
1208 if (!peerReservations_->load(getWalletDB()))
1210 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1214 if (validatorKeys_.keys)
1215 setMaxDisallowedLedger();
1219 auto const supported = []() {
1220 auto const& amendments = detail::supportedAmendments();
1222 supported.reserve(amendments.size());
1223 for (
auto const& [a, vote] : amendments)
1227 f,
"xrpl::ApplicationImp::setup : registered feature");
1229 supported.emplace_back(a, *f, vote);
1233 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1235 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1239 config().AMENDMENT_MAJORITY_TIME,
1243 logs_->journal(
"Amendments"));
1246 Pathfinder::initPathTable();
1248 auto const startUp = config_->START_UP;
1249 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1250 if (startUp == Config::FRESH)
1252 JLOG(m_journal.info()) <<
"Starting new Ledger";
1254 startGenesisLedger();
1257 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1258 startUp == Config::REPLAY)
1260 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1263 config_->START_LEDGER,
1264 startUp == Config::REPLAY,
1265 startUp == Config::LOAD_FILE,
1266 config_->TRAP_TX_HASH))
1268 JLOG(m_journal.error())
1269 <<
"The specified ledger could not be loaded.";
1270 if (config_->FAST_LOAD)
1274 startGenesisLedger();
1282 else if (startUp == Config::NETWORK)
1286 if (!config_->standalone())
1287 m_networkOPs->setNeedNetworkLedger();
1289 startGenesisLedger();
1293 startGenesisLedger();
1296 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1298 m_ledgerMaster->setLedgerRangePresent(
1299 forcedRange->first, forcedRange->second);
1302 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1306 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1308 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1313 if (validatorKeys_.configInvalid())
1316 if (!validatorManifests_->load(
1318 "ValidatorManifests",
1319 validatorKeys_.manifest,
1320 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1322 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1326 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1335 if (validatorKeys_.keys)
1336 localSigningKey = validatorKeys_.keys->publicKey;
1339 if (!validators_->load(
1341 config().section(SECTION_VALIDATORS).values(),
1342 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1343 config().VALIDATOR_LIST_THRESHOLD))
1345 JLOG(m_journal.fatal())
1346 <<
"Invalid entry in validator configuration.";
1351 if (!validatorSites_->load(
1352 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1354 JLOG(m_journal.fatal())
1355 <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1360 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1381 m_collectorManager->collector());
1385 if (!m_networkOPs->beginConsensus(
1386 m_ledgerMaster->getClosedLedger()->header().hash, {}))
1388 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1398 serverHandler_->setup(setup, m_journal);
1403 if (
auto stream = m_journal.fatal())
1405 stream <<
"Unable to setup server handler";
1407 stream <<
": " << e.
what();
1414 if (!config_->standalone())
1418 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1420 JLOG(m_journal.warn())
1421 <<
"No outbound peer connections will be made";
1426 m_networkOPs->setStateTimer();
1430 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1432 m_networkOPs->setStandAlone();
1435 if (config_->canSign())
1437 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1438 "'sign' and 'sign_for'";
1439 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1440 "implications and have";
1441 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1442 "in a future release of";
1443 JLOG(m_journal.warn()) <<
"*** rippled.";
1444 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1445 "transactions please edit your";
1446 JLOG(m_journal.warn())
1447 <<
"*** configuration file and remove the [enable_signing] stanza.";
1448 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1449 "please migrate to a";
1450 JLOG(m_journal.warn())
1451 <<
"*** standalone signing solution as soon as possible.";
1457 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1462 if (!jrReader.
parse(cmd, jvCommand))
1464 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in ["
1465 << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1468 if (!config_->quiet())
1470 JLOG(m_journal.fatal())
1471 <<
"Startup RPC: " << jvCommand <<
std::endl;
1477 {journal(
"RPCHandler"),
1486 RPC::apiMaximumSupportedVersion},
1490 RPC::doCommand(context, jvResult);
1492 if (!config_->quiet())
1494 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1498 validatorSites_->start();
1504ApplicationImp::start(
bool withTimers)
1506 JLOG(m_journal.info()) <<
"Application starting. Version is "
1507 << BuildInfo::getVersionString();
1515 m_io_latency_sampler.start();
1516 m_resolver->start();
1517 m_loadManager->start();
1518 m_shaMapStore->start();
1522 if (grpcServer_->start())
1524 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1526 ledgerCleaner_->start();
1531ApplicationImp::run()
1533 if (!config_->standalone())
1539 getLoadManager().activateStallDetector();
1544 stoppingCondition_.wait(lk, [
this] {
return isTimeToStop.load(); });
1547 JLOG(m_journal.debug()) <<
"Application stopping";
1549 m_io_latency_sampler.cancel_async();
1557 m_io_latency_sampler.cancel();
1559 m_resolver->stop_async();
1569 sweepTimer_.cancel();
1571 catch (boost::system::system_error
const& e)
1573 JLOG(m_journal.error())
1574 <<
"Application: sweepTimer cancel error: " << e.what();
1579 entropyTimer_.cancel();
1581 catch (boost::system::system_error
const& e)
1583 JLOG(m_journal.error())
1584 <<
"Application: entropyTimer cancel error: " << e.what();
1590 using namespace std::chrono_literals;
1592 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1594 mValidations.flush();
1596 validatorSites_->stop();
1599 validatorManifests_->save(
1600 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1601 return validators().listed(pubKey);
1604 publisherManifests_->save(
1605 getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1606 return validators().trustedPublisher(pubKey);
1611 m_loadManager->stop();
1612 m_shaMapStore->stop();
1616 grpcServer_->stop();
1617 m_networkOPs->stop();
1618 serverHandler_->stop();
1619 m_ledgerReplayer->stop();
1620 m_inboundTransactions->stop();
1621 m_inboundLedgers->stop();
1622 ledgerCleaner_->stop();
1623 m_nodeStore->stop();
1626 JLOG(m_journal.info()) <<
"Done.";
1632 if (!isTimeToStop.exchange(
true))
1635 JLOG(m_journal.warn()) <<
"Server stopping";
1637 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1639 stoppingCondition_.notify_all();
1644ApplicationImp::checkSigs()
const
1650ApplicationImp::checkSigs(
bool check)
1656ApplicationImp::isStopping()
const
1658 return isTimeToStop.load();
1662ApplicationImp::fdRequired()
const
1669 needed += 2 * overlay_->limit();
1673 needed +=
std::max(5, m_shaMapStore->fdRequired());
1677 for (
auto const& p : serverHandler_->setup().ports)
1687ApplicationImp::startGenesisLedger()
1690 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1695 m_ledgerMaster->storeLedger(genesis);
1699 next->updateSkipList();
1701 next->header().seq < XRP_LEDGER_EARLIEST_FEES ||
1702 next->read(keylet::fees()),
1703 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1704 next->setImmutable();
1705 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1706 m_ledgerMaster->storeLedger(next);
1707 m_ledgerMaster->switchLCL(next);
1711ApplicationImp::getLastFullLedger()
1713 auto j = journal(
"Ledger");
1723 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES ||
1724 ledger->read(keylet::fees()),
1725 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1726 ledger->setImmutable();
1728 if (getLedgerMaster().haveLedger(seq))
1729 ledger->setValidated();
1731 if (ledger->header().hash ==
hash)
1733 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1737 if (
auto stream = j.error())
1739 stream <<
"Failed on ledger";
1741 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1749 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1763 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1770 if (!reader.
parse(ledgerFile, jLedger))
1772 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1779 if (ledger.
get().isMember(
"result"))
1780 ledger = ledger.
get()[
"result"];
1782 if (ledger.
get().isMember(
"ledger"))
1783 ledger = ledger.
get()[
"ledger"];
1786 auto closeTime = timeKeeper().closeTime();
1787 using namespace std::chrono_literals;
1788 auto closeTimeResolution = 30s;
1789 bool closeTimeEstimated =
false;
1792 if (ledger.
get().isMember(
"accountState"))
1794 if (ledger.
get().isMember(jss::ledger_index))
1796 seq = ledger.
get()[jss::ledger_index].asUInt();
1799 if (ledger.
get().isMember(
"close_time"))
1802 using d = tp::duration;
1803 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1805 if (ledger.
get().isMember(
"close_time_resolution"))
1808 closeTimeResolution =
1809 seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1811 if (ledger.
get().isMember(
"close_time_estimated"))
1813 closeTimeEstimated =
1814 ledger.
get()[
"close_time_estimated"].asBool();
1816 if (ledger.
get().isMember(
"total_coins"))
1818 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1819 ledger.
get()[
"total_coins"].asString());
1822 ledger = ledger.
get()[
"accountState"];
1825 if (!ledger.
get().isArrayOrNull())
1827 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1833 loadLedger->setTotalDrops(totalDrops);
1835 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1841 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1849 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1859 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1867 if (!loadLedger->addSLE(sle))
1869 JLOG(m_journal.fatal())
1870 <<
"Couldn't add serialized ledger: " << uIndex;
1878 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES ||
1879 loadLedger->read(keylet::fees()),
1880 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1881 loadLedger->setAccepted(
1882 closeTime, closeTimeResolution, !closeTimeEstimated);
1888 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1894ApplicationImp::loadOldLedger(
1906 if (!ledgerID.
empty())
1907 loadLedger = loadLedgerFromFile(ledgerID);
1909 else if (ledgerID.
length() == 64)
1913 if (
hash.parseHex(ledgerID))
1924 InboundLedger::Reason::GENERIC,
1927 if (il->checkLocal())
1928 loadLedger = il->getLedger();
1932 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1934 loadLedger = getLastFullLedger();
1953 replayLedger = loadLedger;
1955 JLOG(m_journal.info()) <<
"Loading parent ledger";
1957 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1960 JLOG(m_journal.info())
1961 <<
"Loading parent ledger from node store";
1966 replayLedger->header().parentHash,
1968 InboundLedger::Reason::GENERIC,
1972 if (il->checkLocal())
1973 loadLedger = il->getLedger();
1978 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1980 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1987 using namespace std::chrono_literals;
1988 using namespace date;
1991 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1993 JLOG(m_journal.fatal())
1994 <<
"\n\n*** WARNING ***\n"
1995 "You are replaying a ledger from before "
1996 << to_string(ledgerWarnTimePoint)
1998 "This replay will not handle your ledger as it was "
2000 "handled.\nConsider running an earlier version of rippled "
2002 "get the older rules.\n*** CONTINUING ***\n";
2005 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash
2006 <<
" seq:" << loadLedger->header().seq;
2008 if (loadLedger->header().accountHash.isZero())
2011 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
2013 "xrpl::ApplicationImp::loadOldLedger : ledger is empty");
2018 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
2021 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
2023 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
2029 if (!loadLedger->assertSensible(journal(
"Ledger")))
2032 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
2034 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
2040 m_ledgerMaster->setLedgerRangePresent(
2041 loadLedger->header().seq, loadLedger->header().seq);
2043 m_ledgerMaster->switchLCL(loadLedger);
2044 loadLedger->setValidated();
2045 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
2046 openLedger_.emplace(
2047 loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
2056 for (
auto const& [_, tx] : replayData->orderedTxns())
2059 auto txID = tx->getTransactionID();
2060 if (trapTxID == txID)
2063 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
2069 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2071 openLedger_->modify(
2078 m_ledgerMaster->takeReplay(std::move(replayData));
2080 if (trapTxID && !trapTxID_)
2082 JLOG(m_journal.fatal())
2083 <<
"Ledger " << replayLedger->header().seq
2084 <<
" does not contain the transaction hash " << *trapTxID;
2091 JLOG(m_journal.fatal())
2092 <<
"While loading specified ledger: " << mn.
what();
2095 catch (boost::bad_lexical_cast&)
2097 JLOG(m_journal.fatal())
2098 <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2108 if (!config().ELB_SUPPORT)
2113 reason =
"Server is shutting down";
2117 if (getOPs().isNeedNetworkLedger())
2119 reason =
"Not synchronized with network yet";
2123 if (getOPs().isAmendmentBlocked())
2125 reason =
"Server version too old";
2129 if (getOPs().isUNLBlocked())
2131 reason =
"No valid validator list available";
2135 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2137 reason =
"Not synchronized with network";
2141 if (!getLedgerMaster().isCaughtUp(reason))
2144 if (getFeeTrack().isLoadedLocal())
2146 reason =
"Too much load";
2156 return logs_->journal(name);
2160ApplicationImp::setMaxDisallowedLedger()
2162 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2164 maxDisallowedLedger_ = *seq;
2166 JLOG(m_journal.trace())
2167 <<
"Max persisted ledger is " << maxDisallowedLedger_;
2185 std::move(config), std::move(logs), std::move(timeKeeper));
2191 for (
auto const& [name, ep] : endpoints)
2193 if (!config.
exists(name))
2196 auto& section = config[name];
2197 auto const optPort = section.get(
"port");
2201 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::unique_ptr< RelationalDatabase > mRelationalDatabase
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_
std::mutex stoppingMutex_
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
std::atomic< bool > isTimeToStop
OrderBookDB m_orderBookDB
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
ValidatorSite & validatorSites() override
virtual std::optional< uint256 > const & trapTxID() const override
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
std::condition_variable stoppingCondition_
TaggedCache< uint256, AcceptedLedger > m_acceptedLedgerCache
std::unique_ptr< PathRequests > m_pathRequests
std::unique_ptr< JobQueue > m_jobQueue
LedgerMaster & getLedgerMaster() override
NodeStore::Database & getNodeStore() override
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
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.
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.
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::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
std::pair< PublicKey, SecretKey > getNodeIdentity(Application &app, boost::program_options::variables_map const &cmdline)
The cryptographic credentials identifying this server instance.
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
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)
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< AmendmentTable > make_AmendmentTable(Application &app, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
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< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
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)
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)
HashRouter::Setup setup_HashRouter(Config 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< 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()