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();
221#if XRPL_SINGLE_IO_SERVICE_THREAD
269 config_->section(SECTION_INSIGHT),
270 logs_->journal(
"Collector")))
296 logs_->journal(
"JobQueue"),
305 logs_->journal(
"SHAMapStore")))
312 logs_->journal(
"TaggedCache"))
319 logs_->journal(
"CachedSLEs"))
325 logs_->journal(
"Resource")))
373 logs_->journal(
"TaggedCache"))
385 logs_->journal(
"NetworkOPs"),
391 logs_->journal(
"PeerReservationTable")))
403 config_->legacy(
"database_path"),
404 logs_->journal(
"ValidatorList"),
428 logs_->journal(
"Validations"))
448 logs_->journal(
"Application"),
478 setup(boost::program_options::variables_map
const& cmdline)
override;
480 start(
bool withTimers)
override;
545 "Accessing Application::nodeIdentity() before it is initialized.");
568 "xrpl::ApplicationImp::getServerHandler : non-null server "
573 boost::asio::io_context&
776 overlay_,
"xrpl::ApplicationImp::overlay : non-null overlay");
784 txQ_,
"xrpl::ApplicationImp::getTxQ : non-null transaction queue");
793 "xrpl::ApplicationImp::getRelationalDatabase : non-null "
794 "relational database");
803 "xrpl::ApplicationImp::getWalletDB : non-null wallet database");
820 "xrpl::ApplicationImp::initRelationalDatabase : null wallet "
830 setup.useGlobalPragma =
false;
837 <<
"Failed to initialize SQL databases: " << e.
what();
849 auto j =
logs_->journal(
"NodeObject");
860 JLOG(j.warn()) <<
"Starting node import from '" << source->getName()
864 auto const start = steady_clock::now();
869 duration_cast<seconds>(steady_clock::now() -
start);
870 JLOG(j.warn()) <<
"Node import from '" << source->getName()
871 <<
"' took " << elapsed.count() <<
" seconds.";
894 [
this](boost::system::error_code
const& e) {
895 if (e.value() == boost::system::errc::success)
898 jtSWEEP,
"sweep", [this]() { doSweep(); });
901 if (e.value() != boost::system::errc::success &&
902 e.value() != boost::asio::error::operation_aborted)
905 JLOG(m_journal.error())
906 <<
"Sweep timer got error '" << e.message()
907 <<
"'. Restarting timer.";
915 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
923 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
924 [
this](boost::system::error_code
const& e) {
925 if (e.value() == boost::system::errc::success)
927 crypto_prng().mix_entropy();
931 if (e.value() != boost::system::errc::success &&
932 e.value() != boost::asio::error::operation_aborted)
935 JLOG(m_journal.error())
936 <<
"Entropy timer got error '" << e.message()
937 <<
"'. Restarting timer.";
942 using namespace std::chrono_literals;
943 entropyTimer_.expires_after(5min);
944 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
951 if (!config_->standalone() &&
952 !getRelationalDatabase().transactionDbHasSpace(*config_))
954 signalStop(
"Out of transaction DB space");
963 nodeFamily_.getFullBelowCache();
966 nodeFamily_.getTreeNodeCache();
968 std::size_t const oldFullBelowSize = fullBelowCache->size();
969 std::size_t const oldTreeNodeSize = treeNodeCache->size();
973 JLOG(m_journal.debug())
974 <<
"NodeFamily::FullBelowCache sweep. Size before: "
976 <<
"; size after: " << fullBelowCache->size();
978 JLOG(m_journal.debug())
979 <<
"NodeFamily::TreeNodeCache sweep. Size before: "
980 << oldTreeNodeSize <<
"; size after: " << treeNodeCache->size();
984 getMasterTransaction().getCache();
988 getMasterTransaction().sweep();
990 JLOG(m_journal.debug())
991 <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
992 <<
"; size after: " << masterTxCache.
size();
996 getNodeStore().sweep();
1000 getLedgerMaster().getFetchPackCacheSize();
1002 getLedgerMaster().sweep();
1004 JLOG(m_journal.debug())
1005 <<
"LedgerMaster sweep. Size before: "
1006 << oldLedgerMasterCacheSize <<
"; size after: "
1007 << getLedgerMaster().getFetchPackCacheSize();
1011 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
1013 getTempNodeCache().sweep();
1015 JLOG(m_journal.debug())
1016 <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
1017 <<
"; size after: " << getTempNodeCache().size();
1021 getValidations().sizeOfCurrentCache();
1023 getValidations().sizeOfSeqEnforcersCache();
1025 getValidations().sizeOfByLedgerCache();
1027 getValidations().sizeOfBySequenceCache();
1029 getValidations().expire(m_journal);
1031 JLOG(m_journal.debug())
1032 <<
"Validations Current expire. Size before: "
1033 << oldCurrentCacheSize
1034 <<
"; size after: " << getValidations().sizeOfCurrentCache();
1036 JLOG(m_journal.debug())
1037 <<
"Validations SeqEnforcer expire. Size before: "
1038 << oldSizeSeqEnforcesSize <<
"; size after: "
1039 << getValidations().sizeOfSeqEnforcersCache();
1041 JLOG(m_journal.debug())
1042 <<
"Validations ByLedger expire. Size before: "
1044 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
1046 JLOG(m_journal.debug())
1047 <<
"Validations BySequence expire. Size before: "
1048 << oldBySequenceSize
1049 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
1053 getInboundLedgers().cacheSize();
1055 getInboundLedgers().sweep();
1057 JLOG(m_journal.debug())
1058 <<
"InboundLedgers sweep. Size before: "
1059 << oldInboundLedgersSize
1060 <<
"; size after: " << getInboundLedgers().cacheSize();
1063 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
1064 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
1065 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
1067 getLedgerReplayer().sweep();
1069 JLOG(m_journal.debug())
1070 <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
1071 <<
"; size after: " << getLedgerReplayer().tasksSize();
1073 JLOG(m_journal.debug())
1074 <<
"LedgerReplayer deltas sweep. Size before: "
1076 <<
"; size after: " << getLedgerReplayer().deltasSize();
1078 JLOG(m_journal.debug())
1079 <<
"LedgerReplayer skipLists sweep. Size before: "
1081 <<
"; size after: " << getLedgerReplayer().skipListsSize();
1085 m_acceptedLedgerCache.size();
1087 m_acceptedLedgerCache.sweep();
1089 JLOG(m_journal.debug())
1090 <<
"AcceptedLedgerCache sweep. Size before: "
1091 << oldAcceptedLedgerSize
1092 <<
"; size after: " << m_acceptedLedgerCache.size();
1095 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
1097 cachedSLEs_.sweep();
1099 JLOG(m_journal.debug())
1100 <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
1101 <<
"; size after: " << cachedSLEs_.size();
1111 return maxDisallowedLedger_;
1126 startGenesisLedger();
1129 getLastFullLedger();
1142 setMaxDisallowedLedger();
1149ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1159 m_signals.add(SIGINT);
1160 m_signals.add(SIGTERM);
1161 m_signals.async_wait(
1162 [
this](boost::system::error_code
const& ec,
int signum) {
1164 if (ec == boost::asio::error::operation_aborted)
1167 JLOG(m_journal.info()) <<
"Received signal " << signum;
1169 if (signum == SIGTERM || signum == SIGINT)
1170 signalStop(
"Signal: " + to_string(signum));
1173 auto debug_log = config_->getDebugLogFile();
1175 if (!debug_log.empty())
1180 if (!logs_->open(debug_log))
1181 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1184 if (logs_->threshold() > kDebug)
1185 logs_->threshold(kDebug);
1188 JLOG(m_journal.info()) <<
"Process starting: "
1189 << BuildInfo::getFullVersionString()
1190 <<
", Instance Cookie: " << instanceCookie_;
1192 if (numberOfThreads(*config_) < 2)
1194 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1195 "system configuration.";
1199 logs_->silent(config_->silent());
1201 if (!initRelationalDatabase() || !initNodeStore())
1204 if (!peerReservations_->load(getWalletDB()))
1206 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1210 if (validatorKeys_.keys)
1211 setMaxDisallowedLedger();
1215 auto const supported = []() {
1216 auto const& amendments = detail::supportedAmendments();
1218 supported.reserve(amendments.size());
1219 for (
auto const& [a, vote] : amendments)
1223 f,
"xrpl::ApplicationImp::setup : registered feature");
1225 supported.emplace_back(a, *f, vote);
1229 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1231 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1235 config().AMENDMENT_MAJORITY_TIME,
1239 logs_->journal(
"Amendments"));
1242 Pathfinder::initPathTable();
1244 auto const startUp = config_->START_UP;
1245 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1246 if (startUp == Config::FRESH)
1248 JLOG(m_journal.info()) <<
"Starting new Ledger";
1250 startGenesisLedger();
1253 startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
1254 startUp == Config::REPLAY)
1256 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1259 config_->START_LEDGER,
1260 startUp == Config::REPLAY,
1261 startUp == Config::LOAD_FILE,
1262 config_->TRAP_TX_HASH))
1264 JLOG(m_journal.error())
1265 <<
"The specified ledger could not be loaded.";
1266 if (config_->FAST_LOAD)
1270 startGenesisLedger();
1278 else if (startUp == Config::NETWORK)
1282 if (!config_->standalone())
1283 m_networkOPs->setNeedNetworkLedger();
1285 startGenesisLedger();
1289 startGenesisLedger();
1292 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1294 m_ledgerMaster->setLedgerRangePresent(
1295 forcedRange->first, forcedRange->second);
1298 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1302 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1304 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1309 if (validatorKeys_.configInvalid())
1312 if (!validatorManifests_->load(
1314 "ValidatorManifests",
1315 validatorKeys_.manifest,
1316 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1318 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1322 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1331 if (validatorKeys_.keys)
1332 localSigningKey = validatorKeys_.keys->publicKey;
1335 if (!validators_->load(
1337 config().section(SECTION_VALIDATORS).values(),
1338 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1339 config().VALIDATOR_LIST_THRESHOLD))
1341 JLOG(m_journal.fatal())
1342 <<
"Invalid entry in validator configuration.";
1347 if (!validatorSites_->load(
1348 config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1350 JLOG(m_journal.fatal())
1351 <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1356 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1377 m_collectorManager->collector());
1381 if (!m_networkOPs->beginConsensus(
1382 m_ledgerMaster->getClosedLedger()->header().hash, {}))
1384 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1394 serverHandler_->setup(setup, m_journal);
1399 if (
auto stream = m_journal.fatal())
1401 stream <<
"Unable to setup server handler";
1403 stream <<
": " << e.
what();
1410 if (!config_->standalone())
1414 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1416 JLOG(m_journal.warn())
1417 <<
"No outbound peer connections will be made";
1422 m_networkOPs->setStateTimer();
1426 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1428 m_networkOPs->setStandAlone();
1431 if (config_->canSign())
1433 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1434 "'sign' and 'sign_for'";
1435 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1436 "implications and have";
1437 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1438 "in a future release of";
1439 JLOG(m_journal.warn()) <<
"*** rippled.";
1440 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1441 "transactions please edit your";
1442 JLOG(m_journal.warn())
1443 <<
"*** configuration file and remove the [enable_signing] stanza.";
1444 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1445 "please migrate to a";
1446 JLOG(m_journal.warn())
1447 <<
"*** standalone signing solution as soon as possible.";
1453 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1458 if (!jrReader.
parse(cmd, jvCommand))
1460 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in ["
1461 << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1464 if (!config_->quiet())
1466 JLOG(m_journal.fatal())
1467 <<
"Startup RPC: " << jvCommand <<
std::endl;
1473 {journal(
"RPCHandler"),
1482 RPC::apiMaximumSupportedVersion},
1486 RPC::doCommand(context, jvResult);
1488 if (!config_->quiet())
1490 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1494 validatorSites_->start();
1500ApplicationImp::start(
bool withTimers)
1502 JLOG(m_journal.info()) <<
"Application starting. Version is "
1503 << BuildInfo::getVersionString();
1511 m_io_latency_sampler.start();
1512 m_resolver->start();
1513 m_loadManager->start();
1514 m_shaMapStore->start();
1518 if (grpcServer_->start())
1520 *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1522 ledgerCleaner_->start();
1527ApplicationImp::run()
1529 if (!config_->standalone())
1535 getLoadManager().activateStallDetector();
1540 JLOG(m_journal.debug()) <<
"Application stopping";
1542 m_io_latency_sampler.cancel_async();
1550 m_io_latency_sampler.cancel();
1552 m_resolver->stop_async();
1562 sweepTimer_.cancel();
1564 catch (boost::system::system_error
const& e)
1566 JLOG(m_journal.error())
1567 <<
"Application: sweepTimer cancel error: " << e.what();
1572 entropyTimer_.cancel();
1574 catch (boost::system::system_error
const& e)
1576 JLOG(m_journal.error())
1577 <<
"Application: entropyTimer cancel error: " << e.what();
1583 using namespace std::chrono_literals;
1585 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1587 mValidations.flush();
1589 validatorSites_->stop();
1592 validatorManifests_->save(
1593 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
1594 return validators().listed(pubKey);
1597 publisherManifests_->save(
1598 getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1599 return validators().trustedPublisher(pubKey);
1604 m_loadManager->stop();
1605 m_shaMapStore->stop();
1609 grpcServer_->stop();
1610 m_networkOPs->stop();
1611 serverHandler_->stop();
1612 m_ledgerReplayer->stop();
1613 m_inboundTransactions->stop();
1614 m_inboundLedgers->stop();
1615 ledgerCleaner_->stop();
1616 m_nodeStore->stop();
1619 JLOG(m_journal.info()) <<
"Done.";
1628 JLOG(m_journal.warn()) <<
"Server stopping";
1630 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1632 isTimeToStop.notify_all();
1637ApplicationImp::checkSigs()
const
1643ApplicationImp::checkSigs(
bool check)
1649ApplicationImp::isStopping()
const
1655ApplicationImp::fdRequired()
const
1662 needed += 2 * overlay_->limit();
1666 needed +=
std::max(5, m_shaMapStore->fdRequired());
1670 for (
auto const& p : serverHandler_->setup().ports)
1680ApplicationImp::startGenesisLedger()
1683 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
1688 m_ledgerMaster->storeLedger(genesis);
1692 next->updateSkipList();
1694 next->header().seq < XRP_LEDGER_EARLIEST_FEES ||
1695 next->read(keylet::fees()),
1696 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1697 next->setImmutable();
1698 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1699 m_ledgerMaster->storeLedger(next);
1700 m_ledgerMaster->switchLCL(next);
1704ApplicationImp::getLastFullLedger()
1706 auto j = journal(
"Ledger");
1716 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES ||
1717 ledger->read(keylet::fees()),
1718 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1719 ledger->setImmutable();
1721 if (getLedgerMaster().haveLedger(seq))
1722 ledger->setValidated();
1724 if (ledger->header().hash ==
hash)
1726 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1730 if (
auto stream = j.error())
1732 stream <<
"Failed on ledger";
1734 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1742 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1756 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1763 if (!reader.
parse(ledgerFile, jLedger))
1765 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1772 if (ledger.
get().isMember(
"result"))
1773 ledger = ledger.
get()[
"result"];
1775 if (ledger.
get().isMember(
"ledger"))
1776 ledger = ledger.
get()[
"ledger"];
1779 auto closeTime = timeKeeper().closeTime();
1780 using namespace std::chrono_literals;
1781 auto closeTimeResolution = 30s;
1782 bool closeTimeEstimated =
false;
1785 if (ledger.
get().isMember(
"accountState"))
1787 if (ledger.
get().isMember(jss::ledger_index))
1789 seq = ledger.
get()[jss::ledger_index].asUInt();
1792 if (ledger.
get().isMember(
"close_time"))
1795 using d = tp::duration;
1796 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1798 if (ledger.
get().isMember(
"close_time_resolution"))
1801 closeTimeResolution =
1802 seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1804 if (ledger.
get().isMember(
"close_time_estimated"))
1806 closeTimeEstimated =
1807 ledger.
get()[
"close_time_estimated"].asBool();
1809 if (ledger.
get().isMember(
"total_coins"))
1811 totalDrops = beast::lexicalCastThrow<std::uint64_t>(
1812 ledger.
get()[
"total_coins"].asString());
1815 ledger = ledger.
get()[
"accountState"];
1818 if (!ledger.
get().isArrayOrNull())
1820 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1826 loadLedger->setTotalDrops(totalDrops);
1828 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1834 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1842 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1852 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1860 if (!loadLedger->addSLE(sle))
1862 JLOG(m_journal.fatal())
1863 <<
"Couldn't add serialized ledger: " << uIndex;
1871 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES ||
1872 loadLedger->read(keylet::fees()),
1873 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1874 loadLedger->setAccepted(
1875 closeTime, closeTimeResolution, !closeTimeEstimated);
1881 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1887ApplicationImp::loadOldLedger(
1899 if (!ledgerID.
empty())
1900 loadLedger = loadLedgerFromFile(ledgerID);
1902 else if (ledgerID.
length() == 64)
1906 if (
hash.parseHex(ledgerID))
1917 InboundLedger::Reason::GENERIC,
1920 if (il->checkLocal())
1921 loadLedger = il->getLedger();
1925 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1927 loadLedger = getLastFullLedger();
1946 replayLedger = loadLedger;
1948 JLOG(m_journal.info()) <<
"Loading parent ledger";
1950 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1953 JLOG(m_journal.info())
1954 <<
"Loading parent ledger from node store";
1959 replayLedger->header().parentHash,
1961 InboundLedger::Reason::GENERIC,
1965 if (il->checkLocal())
1966 loadLedger = il->getLedger();
1971 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1973 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1980 using namespace std::chrono_literals;
1981 using namespace date;
1984 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1986 JLOG(m_journal.fatal())
1987 <<
"\n\n*** WARNING ***\n"
1988 "You are replaying a ledger from before "
1989 << to_string(ledgerWarnTimePoint)
1991 "This replay will not handle your ledger as it was "
1993 "handled.\nConsider running an earlier version of rippled "
1995 "get the older rules.\n*** CONTINUING ***\n";
1998 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash
1999 <<
" seq:" << loadLedger->header().seq;
2001 if (loadLedger->header().accountHash.isZero())
2004 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
2006 "xrpl::ApplicationImp::loadOldLedger : ledger is empty");
2011 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
2014 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
2016 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
2022 if (!loadLedger->assertSensible(journal(
"Ledger")))
2025 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
2027 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
2033 m_ledgerMaster->setLedgerRangePresent(
2034 loadLedger->header().seq, loadLedger->header().seq);
2036 m_ledgerMaster->switchLCL(loadLedger);
2037 loadLedger->setValidated();
2038 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
2039 openLedger_.emplace(
2040 loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
2049 for (
auto const& [_, tx] : replayData->orderedTxns())
2052 auto txID = tx->getTransactionID();
2053 if (trapTxID == txID)
2056 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
2062 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
2064 openLedger_->modify(
2071 m_ledgerMaster->takeReplay(std::move(replayData));
2073 if (trapTxID && !trapTxID_)
2075 JLOG(m_journal.fatal())
2076 <<
"Ledger " << replayLedger->header().seq
2077 <<
" does not contain the transaction hash " << *trapTxID;
2084 JLOG(m_journal.fatal())
2085 <<
"While loading specified ledger: " << mn.
what();
2088 catch (boost::bad_lexical_cast&)
2090 JLOG(m_journal.fatal())
2091 <<
"Ledger specified '" << ledgerID <<
"' is not valid";
2101 if (!config().ELB_SUPPORT)
2106 reason =
"Server is shutting down";
2110 if (getOPs().isNeedNetworkLedger())
2112 reason =
"Not synchronized with network yet";
2116 if (getOPs().isAmendmentBlocked())
2118 reason =
"Server version too old";
2122 if (getOPs().isUNLBlocked())
2124 reason =
"No valid validator list available";
2128 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
2130 reason =
"Not synchronized with network";
2134 if (!getLedgerMaster().isCaughtUp(reason))
2137 if (getFeeTrack().isLoadedLocal())
2139 reason =
"Too much load";
2149 return logs_->journal(name);
2153ApplicationImp::setMaxDisallowedLedger()
2155 auto seq = getRelationalDatabase().getMaxLedgerSeq();
2157 maxDisallowedLedger_ = *seq;
2159 JLOG(m_journal.trace())
2160 <<
"Max persisted ledger is " << maxDisallowedLedger_;
2178 std::move(config), std::move(logs), std::move(timeKeeper));
2184 for (
auto const& [name, ep] : endpoints)
2186 if (!config.
exists(name))
2189 auto& section = config[name];
2190 auto const optPort = section.get(
"port");
2194 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_
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
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::atomic_flag isTimeToStop
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
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()