1#include <xrpld/app/consensus/RCLValidations.h>
2#include <xrpld/app/ledger/InboundLedgers.h>
3#include <xrpld/app/ledger/InboundTransactions.h>
4#include <xrpld/app/ledger/LedgerCleaner.h>
5#include <xrpld/app/ledger/LedgerMaster.h>
6#include <xrpld/app/ledger/LedgerReplayer.h>
7#include <xrpld/app/ledger/LedgerToJson.h>
8#include <xrpld/app/ledger/OpenLedger.h>
9#include <xrpld/app/ledger/OrderBookDBImpl.h>
10#include <xrpld/app/ledger/PendingSaves.h>
11#include <xrpld/app/ledger/TransactionMaster.h>
12#include <xrpld/app/main/Application.h>
13#include <xrpld/app/main/BasicApp.h>
14#include <xrpld/app/main/GRPCServer.h>
15#include <xrpld/app/main/LoadManager.h>
16#include <xrpld/app/main/NodeIdentity.h>
17#include <xrpld/app/main/NodeStoreScheduler.h>
18#include <xrpld/app/misc/AmendmentTable.h>
19#include <xrpld/app/misc/LoadFeeTrack.h>
20#include <xrpld/app/misc/SHAMapStore.h>
21#include <xrpld/app/misc/TxQ.h>
22#include <xrpld/app/misc/ValidatorKeys.h>
23#include <xrpld/app/misc/ValidatorSite.h>
24#include <xrpld/app/misc/make_NetworkOPs.h>
25#include <xrpld/app/misc/setup_HashRouter.h>
26#include <xrpld/app/paths/PathRequests.h>
27#include <xrpld/app/rdb/backend/SQLiteDatabase.h>
28#include <xrpld/app/tx/apply.h>
29#include <xrpld/overlay/Cluster.h>
30#include <xrpld/overlay/PeerSet.h>
31#include <xrpld/overlay/make_Overlay.h>
32#include <xrpld/shamap/NodeFamily.h>
34#include <xrpl/basics/ByteUtilities.h>
35#include <xrpl/basics/ResolverAsio.h>
36#include <xrpl/basics/random.h>
37#include <xrpl/beast/asio/io_latency_probe.h>
38#include <xrpl/beast/core/LexicalCast.h>
39#include <xrpl/core/HashRouter.h>
40#include <xrpl/core/PeerReservationTable.h>
41#include <xrpl/core/PerfLog.h>
42#include <xrpl/crypto/csprng.h>
43#include <xrpl/json/json_reader.h>
44#include <xrpl/nodestore/DummyScheduler.h>
45#include <xrpl/protocol/ApiVersion.h>
46#include <xrpl/protocol/BuildInfo.h>
47#include <xrpl/protocol/Feature.h>
48#include <xrpl/protocol/Protocol.h>
49#include <xrpl/protocol/STParsedJSON.h>
50#include <xrpl/rdb/DatabaseCon.h>
51#include <xrpl/resource/Fees.h>
52#include <xrpl/server/Wallet.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)
102 template <
class Duration>
107 auto const lastSample = ceil<milliseconds>(elapsed);
111 if (lastSample >= 10ms)
113 if (lastSample >= 500ms)
115 JLOG(
m_journal.
warn()) <<
"io_context latency = " << lastSample.count();
216#if XRPL_SINGLE_IO_SERVICE_THREAD
247 perf::setup_PerfLog(
config_->section(
"perf"),
config_->CONFIG_DIR),
279 logs_->journal(
"JobQueue"),
308 logs_->journal(
"LedgerMaster")))
329 logs_->journal(
"TaggedCache"))
341 logs_->journal(
"NetworkOPs"),
356 config_->legacy(
"database_path"),
357 logs_->journal(
"ValidatorList"),
392 logs_->journal(
"Application"),
422 setup(boost::program_options::variables_map
const& cmdline)
override;
424 start(
bool withTimers)
override;
488 LogicError(
"Accessing Application::nodeIdentity() before it is initialized.");
511 "xrpl::ApplicationImp::getServerHandler : non-null server "
516 boost::asio::io_context&
718 XRPL_ASSERT(
overlay_,
"xrpl::ApplicationImp::overlay : non-null overlay");
725 XRPL_ASSERT(
txQ_,
"xrpl::ApplicationImp::getTxQ : non-null transaction queue");
734 "xrpl::ApplicationImp::getRelationalDatabase : non-null "
735 "relational database");
742 XRPL_ASSERT(
mWalletDB,
"xrpl::ApplicationImp::getWalletDB : non-null wallet database");
759 "xrpl::ApplicationImp::initRelationalDatabase : null wallet "
768 setup.useGlobalPragma =
false;
786 auto j =
logs_->journal(
"NodeObject");
795 JLOG(j.warn()) <<
"Starting node import from '" << source->getName() <<
"' to '" <<
m_nodeStore->getName()
799 auto const start = steady_clock::now();
803 auto const elapsed = duration_cast<seconds>(steady_clock::now() -
start);
804 JLOG(j.warn()) <<
"Node import from '" << source->getName() <<
"' took " << elapsed.count() <<
" seconds.";
826 if (
auto optionalCountedHandler =
waitHandlerCounter_.wrap([
this](boost::system::error_code
const& e) {
827 if (e.value() == boost::system::errc::success)
829 m_jobQueue->addJob(jtSWEEP,
"sweep", [this]() { doSweep(); });
832 if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted)
835 JLOG(m_journal.error()) <<
"Sweep timer got error '" << e.message() <<
"'. Restarting timer.";
843 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
851 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap([
this](boost::system::error_code
const& e) {
852 if (e.value() == boost::system::errc::success)
854 crypto_prng().mix_entropy();
858 if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted)
861 JLOG(m_journal.error()) <<
"Entropy timer got error '" << e.message() <<
"'. Restarting timer.";
866 using namespace std::chrono_literals;
867 entropyTimer_.expires_after(5min);
868 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
875 XRPL_ASSERT(relationalDatabase_,
"xrpl::ApplicationImp::doSweep : non-null relational database");
876 if (!config_->standalone() && !relationalDatabase_->transactionDbHasSpace(*config_))
878 signalStop(
"Out of transaction DB space");
890 std::size_t const oldFullBelowSize = fullBelowCache->size();
891 std::size_t const oldTreeNodeSize = treeNodeCache->size();
895 JLOG(m_journal.debug()) <<
"NodeFamily::FullBelowCache sweep. Size before: " << oldFullBelowSize
896 <<
"; size after: " << fullBelowCache->size();
898 JLOG(m_journal.debug()) <<
"NodeFamily::TreeNodeCache sweep. Size before: " << oldTreeNodeSize
899 <<
"; size after: " << treeNodeCache->size();
906 getMasterTransaction().sweep();
908 JLOG(m_journal.debug()) <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
909 <<
"; size after: " << masterTxCache.
size();
912 std::size_t const oldLedgerMasterCacheSize = getLedgerMaster().getFetchPackCacheSize();
914 getLedgerMaster().sweep();
916 JLOG(m_journal.debug()) <<
"LedgerMaster sweep. Size before: " << oldLedgerMasterCacheSize
917 <<
"; size after: " << getLedgerMaster().getFetchPackCacheSize();
921 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
923 getTempNodeCache().sweep();
925 JLOG(m_journal.debug()) <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
926 <<
"; size after: " << getTempNodeCache().size();
929 std::size_t const oldCurrentCacheSize = getValidations().sizeOfCurrentCache();
930 std::size_t const oldSizeSeqEnforcesSize = getValidations().sizeOfSeqEnforcersCache();
931 std::size_t const oldByLedgerSize = getValidations().sizeOfByLedgerCache();
932 std::size_t const oldBySequenceSize = getValidations().sizeOfBySequenceCache();
934 getValidations().expire(m_journal);
936 JLOG(m_journal.debug()) <<
"Validations Current expire. Size before: " << oldCurrentCacheSize
937 <<
"; size after: " << getValidations().sizeOfCurrentCache();
939 JLOG(m_journal.debug()) <<
"Validations SeqEnforcer expire. Size before: " << oldSizeSeqEnforcesSize
940 <<
"; size after: " << getValidations().sizeOfSeqEnforcersCache();
942 JLOG(m_journal.debug()) <<
"Validations ByLedger expire. Size before: " << oldByLedgerSize
943 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
945 JLOG(m_journal.debug()) <<
"Validations BySequence expire. Size before: " << oldBySequenceSize
946 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
949 std::size_t const oldInboundLedgersSize = getInboundLedgers().cacheSize();
951 getInboundLedgers().sweep();
953 JLOG(m_journal.debug()) <<
"InboundLedgers sweep. Size before: " << oldInboundLedgersSize
954 <<
"; size after: " << getInboundLedgers().cacheSize();
957 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
958 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
959 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
961 getLedgerReplayer().sweep();
963 JLOG(m_journal.debug()) <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
964 <<
"; size after: " << getLedgerReplayer().tasksSize();
966 JLOG(m_journal.debug()) <<
"LedgerReplayer deltas sweep. Size before: " << oldDeltasSize
967 <<
"; size after: " << getLedgerReplayer().deltasSize();
969 JLOG(m_journal.debug()) <<
"LedgerReplayer skipLists sweep. Size before: " << oldSkipListsSize
970 <<
"; size after: " << getLedgerReplayer().skipListsSize();
973 std::size_t const oldAcceptedLedgerSize = m_acceptedLedgerCache.size();
975 m_acceptedLedgerCache.sweep();
977 JLOG(m_journal.debug()) <<
"AcceptedLedgerCache sweep. Size before: " << oldAcceptedLedgerSize
978 <<
"; size after: " << m_acceptedLedgerCache.size();
981 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
985 JLOG(m_journal.debug()) <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
986 <<
"; size after: " << cachedSLEs_.size();
996 return maxDisallowedLedger_;
1011 startGenesisLedger();
1014 getLastFullLedger();
1023 setMaxDisallowedLedger();
1036ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1046 m_signals.
add(SIGINT);
1047 m_signals.add(SIGTERM);
1048 m_signals.async_wait([
this](boost::system::error_code
const& ec,
int signum) {
1050 if (ec == boost::asio::error::operation_aborted)
1053 JLOG(m_journal.info()) <<
"Received signal " << signum;
1055 if (signum == SIGTERM || signum == SIGINT)
1056 signalStop(
"Signal: " + to_string(signum));
1059 auto debug_log = config_->getDebugLogFile();
1061 if (!debug_log.empty())
1066 if (!logs_->open(debug_log))
1067 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1070 if (logs_->threshold() > kDebug)
1071 logs_->threshold(kDebug);
1074 JLOG(m_journal.info()) <<
"Process starting: " << BuildInfo::getFullVersionString()
1075 <<
", Instance Cookie: " << instanceCookie_;
1077 if (numberOfThreads(*config_) < 2)
1079 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1080 "system configuration.";
1084 logs_->silent(config_->silent());
1086 if (!initRelationalDatabase() || !initNodeStore())
1089 if (!peerReservations_->load(getWalletDB()))
1091 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1095 if (validatorKeys_.keys)
1096 setMaxDisallowedLedger();
1100 auto const supported = []() {
1101 auto const& amendments = detail::supportedAmendments();
1103 supported.reserve(amendments.size());
1104 for (
auto const& [a, vote] : amendments)
1107 XRPL_ASSERT(f,
"xrpl::ApplicationImp::setup : registered feature");
1109 supported.emplace_back(a, *f, vote);
1113 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1115 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1118 *
this, config().AMENDMENT_MAJORITY_TIME, supported, upVoted, downVoted, logs_->journal(
"Amendments"));
1121 Pathfinder::initPathTable();
1123 auto const startUp = config_->START_UP;
1124 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1125 if (startUp == StartUpType::FRESH)
1127 JLOG(m_journal.info()) <<
"Starting new Ledger";
1129 startGenesisLedger();
1131 else if (startUp == StartUpType::LOAD || startUp == StartUpType::LOAD_FILE || startUp == StartUpType::REPLAY)
1133 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1136 config_->START_LEDGER,
1137 startUp == StartUpType::REPLAY,
1138 startUp == StartUpType::LOAD_FILE,
1139 config_->TRAP_TX_HASH))
1141 JLOG(m_journal.error()) <<
"The specified ledger could not be loaded.";
1142 if (config_->FAST_LOAD)
1146 startGenesisLedger();
1154 else if (startUp == StartUpType::NETWORK)
1158 if (!config_->standalone())
1159 m_networkOPs->setNeedNetworkLedger();
1161 startGenesisLedger();
1165 startGenesisLedger();
1168 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1170 m_ledgerMaster->setLedgerRangePresent(forcedRange->first, forcedRange->second);
1173 m_orderBookDB->setup(getLedgerMaster().getCurrentLedger());
1177 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1179 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1184 if (validatorKeys_.configInvalid())
1187 if (!validatorManifests_->load(
1189 "ValidatorManifests",
1190 validatorKeys_.manifest,
1191 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1193 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1197 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1206 if (validatorKeys_.keys)
1207 localSigningKey = validatorKeys_.keys->publicKey;
1210 if (!validators_->load(
1212 config().section(SECTION_VALIDATORS).values(),
1213 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1214 config().VALIDATOR_LIST_THRESHOLD))
1216 JLOG(m_journal.fatal()) <<
"Invalid entry in validator configuration.";
1221 if (!validatorSites_->load(config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1223 JLOG(m_journal.fatal()) <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1228 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1249 m_collectorManager->collector());
1253 if (!m_networkOPs->beginConsensus(m_ledgerMaster->getClosedLedger()->header().hash, {}))
1255 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1264 serverHandler_->setup(setup, m_journal);
1269 if (
auto stream = m_journal.fatal())
1271 stream <<
"Unable to setup server handler";
1273 stream <<
": " << e.
what();
1280 if (!config_->standalone())
1284 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1286 JLOG(m_journal.warn()) <<
"No outbound peer connections will be made";
1291 m_networkOPs->setStateTimer();
1295 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1297 m_networkOPs->setStandAlone();
1300 if (config_->canSign())
1302 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1303 "'sign' and 'sign_for'";
1304 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1305 "implications and have";
1306 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1307 "in a future release of";
1308 JLOG(m_journal.warn()) <<
"*** rippled.";
1309 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1310 "transactions please edit your";
1311 JLOG(m_journal.warn()) <<
"*** configuration file and remove the [enable_signing] stanza.";
1312 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1313 "please migrate to a";
1314 JLOG(m_journal.warn()) <<
"*** standalone signing solution as soon as possible.";
1320 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1325 if (!jrReader.
parse(cmd, jvCommand))
1327 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in [" << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1330 if (!config_->quiet())
1332 JLOG(m_journal.fatal()) <<
"Startup RPC: " << jvCommand <<
std::endl;
1338 {journal(
"RPCHandler"),
1347 RPC::apiMaximumSupportedVersion},
1351 RPC::doCommand(context, jvResult);
1353 if (!config_->quiet())
1355 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1359 validatorSites_->start();
1365ApplicationImp::start(
bool withTimers)
1367 JLOG(m_journal.info()) <<
"Application starting. Version is " << BuildInfo::getVersionString();
1375 m_io_latency_sampler.start();
1376 m_resolver->start();
1377 m_loadManager->start();
1378 m_shaMapStore->start();
1382 if (grpcServer_->start())
1383 fixConfigPorts(*config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1385 ledgerCleaner_->start();
1390ApplicationImp::run()
1392 if (!config_->standalone())
1398 getLoadManager().activateStallDetector();
1403 JLOG(m_journal.debug()) <<
"Application stopping";
1405 m_io_latency_sampler.cancel_async();
1413 m_io_latency_sampler.cancel();
1415 m_resolver->stop_async();
1425 sweepTimer_.cancel();
1427 catch (boost::system::system_error
const& e)
1429 JLOG(m_journal.error()) <<
"Application: sweepTimer cancel error: " << e.what();
1434 entropyTimer_.cancel();
1436 catch (boost::system::system_error
const& e)
1438 JLOG(m_journal.error()) <<
"Application: entropyTimer cancel error: " << e.what();
1444 using namespace std::chrono_literals;
1446 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1448 mValidations.flush();
1450 validatorSites_->stop();
1453 validatorManifests_->save(
1454 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
return validators().listed(pubKey); });
1456 publisherManifests_->save(getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1457 return validators().trustedPublisher(pubKey);
1462 m_loadManager->stop();
1463 m_shaMapStore->stop();
1467 grpcServer_->stop();
1468 m_networkOPs->stop();
1469 serverHandler_->stop();
1470 m_ledgerReplayer->stop();
1471 m_inboundTransactions->stop();
1472 m_inboundLedgers->stop();
1473 ledgerCleaner_->stop();
1474 m_nodeStore->stop();
1477 JLOG(m_journal.info()) <<
"Done.";
1486 JLOG(m_journal.warn()) <<
"Server stopping";
1488 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1490 isTimeToStop.notify_all();
1495ApplicationImp::checkSigs()
const
1501ApplicationImp::checkSigs(
bool check)
1507ApplicationImp::isStopping()
const
1513ApplicationImp::fdRequired()
const
1520 needed += 2 * overlay_->limit();
1524 needed +=
std::max(5, m_shaMapStore->fdRequired());
1528 for (
auto const& p : serverHandler_->setup().ports)
1538ApplicationImp::startGenesisLedger()
1541 (config_->START_UP == StartUpType::FRESH) ? m_amendmentTable->getDesired() :
std::vector<uint256>{};
1545 m_ledgerMaster->storeLedger(genesis);
1548 next->updateSkipList();
1550 next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()),
1551 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1552 next->setImmutable();
1553 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1554 m_ledgerMaster->storeLedger(next);
1555 m_ledgerMaster->switchLCL(next);
1559ApplicationImp::getLastFullLedger()
1561 auto j = journal(
"Ledger");
1571 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
1572 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1573 ledger->setImmutable();
1575 if (getLedgerMaster().haveLedger(seq))
1576 ledger->setValidated();
1578 if (ledger->header().hash ==
hash)
1580 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1584 if (
auto stream = j.error())
1586 stream <<
"Failed on ledger";
1588 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1596 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1610 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1617 if (!reader.
parse(ledgerFile, jLedger))
1619 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1626 if (ledger.
get().isMember(
"result"))
1627 ledger = ledger.
get()[
"result"];
1629 if (ledger.
get().isMember(
"ledger"))
1630 ledger = ledger.
get()[
"ledger"];
1633 auto closeTime = timeKeeper().closeTime();
1634 using namespace std::chrono_literals;
1635 auto closeTimeResolution = 30s;
1636 bool closeTimeEstimated =
false;
1639 if (ledger.
get().isMember(
"accountState"))
1641 if (ledger.
get().isMember(jss::ledger_index))
1643 seq = ledger.
get()[jss::ledger_index].asUInt();
1646 if (ledger.
get().isMember(
"close_time"))
1649 using d = tp::duration;
1650 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1652 if (ledger.
get().isMember(
"close_time_resolution"))
1655 closeTimeResolution =
seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1657 if (ledger.
get().isMember(
"close_time_estimated"))
1659 closeTimeEstimated = ledger.
get()[
"close_time_estimated"].asBool();
1661 if (ledger.
get().isMember(
"total_coins"))
1663 totalDrops = beast::lexicalCastThrow<std::uint64_t>(ledger.
get()[
"total_coins"].asString());
1666 ledger = ledger.
get()[
"accountState"];
1669 if (!ledger.
get().isArrayOrNull())
1671 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1676 loadLedger->setTotalDrops(totalDrops);
1678 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1684 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1692 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1702 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1710 if (!loadLedger->addSLE(sle))
1712 JLOG(m_journal.fatal()) <<
"Couldn't add serialized ledger: " << uIndex;
1720 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()),
1721 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1722 loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated);
1728 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1734ApplicationImp::loadOldLedger(
1746 if (!ledgerID.
empty())
1747 loadLedger = loadLedgerFromFile(ledgerID);
1749 else if (ledgerID.
length() == 64)
1753 if (
hash.parseHex(ledgerID))
1762 if (il->checkLocal())
1763 loadLedger = il->getLedger();
1767 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1769 loadLedger = getLastFullLedger();
1788 replayLedger = loadLedger;
1790 JLOG(m_journal.info()) <<
"Loading parent ledger";
1792 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1795 JLOG(m_journal.info()) <<
"Loading parent ledger from node store";
1800 replayLedger->header().parentHash,
1802 InboundLedger::Reason::GENERIC,
1806 if (il->checkLocal())
1807 loadLedger = il->getLedger();
1812 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1814 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1821 using namespace std::chrono_literals;
1822 using namespace date;
1825 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1827 JLOG(m_journal.fatal()) <<
"\n\n*** WARNING ***\n"
1828 "You are replaying a ledger from before "
1829 << to_string(ledgerWarnTimePoint)
1831 "This replay will not handle your ledger as it was "
1833 "handled.\nConsider running an earlier version of rippled "
1835 "get the older rules.\n*** CONTINUING ***\n";
1838 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash <<
" seq:" << loadLedger->header().seq;
1840 if (loadLedger->header().accountHash.isZero())
1843 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
1844 UNREACHABLE(
"xrpl::ApplicationImp::loadOldLedger : ledger is empty");
1849 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
1852 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
1854 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
1860 if (!loadLedger->assertSensible(journal(
"Ledger")))
1863 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
1865 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
1871 m_ledgerMaster->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq);
1873 m_ledgerMaster->switchLCL(loadLedger);
1874 loadLedger->setValidated();
1875 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
1876 openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
1884 for (
auto const& [_, tx] : replayData->orderedTxns())
1887 auto txID = tx->getTransactionID();
1888 if (trapTxID == txID)
1891 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
1897 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
1905 m_ledgerMaster->takeReplay(std::move(replayData));
1907 if (trapTxID && !trapTxID_)
1909 JLOG(m_journal.fatal()) <<
"Ledger " << replayLedger->header().seq
1910 <<
" does not contain the transaction hash " << *trapTxID;
1917 JLOG(m_journal.fatal()) <<
"While loading specified ledger: " << mn.
what();
1920 catch (boost::bad_lexical_cast&)
1922 JLOG(m_journal.fatal()) <<
"Ledger specified '" << ledgerID <<
"' is not valid";
1932 if (!config().ELB_SUPPORT)
1937 reason =
"Server is shutting down";
1941 if (getOPs().isNeedNetworkLedger())
1943 reason =
"Not synchronized with network yet";
1947 if (getOPs().isAmendmentBlocked())
1949 reason =
"Server version too old";
1953 if (getOPs().isUNLBlocked())
1955 reason =
"No valid validator list available";
1959 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
1961 reason =
"Not synchronized with network";
1965 if (!getLedgerMaster().isCaughtUp(reason))
1968 if (getFeeTrack().isLoadedLocal())
1970 reason =
"Too much load";
1980 return logs_->journal(name);
1984ApplicationImp::setMaxDisallowedLedger()
1986 auto seq = getRelationalDatabase().getMaxLedgerSeq();
1988 maxDisallowedLedger_ = *seq;
1990 JLOG(m_journal.trace()) <<
"Max persisted ledger is " << maxDisallowedLedger_;
2010 for (
auto const& [name, ep] : endpoints)
2012 if (!config.
exists(name))
2015 auto& section = config[name];
2016 auto const optPort = section.get(
"port");
2019 std::uint16_t const port = beast::lexicalCast<std::uint16_t>(*optPort);
boost::asio::io_context & get_io_context()
Unserialize a JSON document into a Value.
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
bool isObjectOrNull() const
Value removeMember(char const *key)
Remove and return the named member.
std::string asString() const
Returns the unquoted string value.
A generic endpoint for log messages.
std::string const & name() const
Returns the name of this source.
void add(Source &source)
Add a child source.
Abstract stream with RAII containers that produce a property tree.
A metric for reporting event timing.
void notify(std::chrono::duration< Rep, Period > const &value) const
Push an event notification.
Measures handler latency on an io_context queue.
void sample(Handler &&handler)
Initiate continuous i/o latency sampling.
void cancel()
Cancel all pending i/o.
The amendment table stores the list of enabled and potential amendments.
beast::insight::Event m_event
beast::io_latency_probe< std::chrono::steady_clock > m_probe
void operator()(Duration const &elapsed)
std::atomic< std::chrono::milliseconds > lastSample_
io_latency_sampler(beast::insight::Event ev, beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context &ios)
std::chrono::milliseconds get() const
LedgerReplayer & getLedgerReplayer() override
Application::MutexType & getMasterMutex() override
std::optional< std::pair< PublicKey, SecretKey > > nodeIdentity_
InboundLedgers & getInboundLedgers() override
NodeCache m_tempNodeCache
std::unique_ptr< LedgerCleaner > ledgerCleaner_
std::unique_ptr< LoadManager > m_loadManager
void start(bool withTimers) override
LoadFeeTrack & getFeeTrack() override
Cluster & cluster() override
std::unique_ptr< perf::PerfLog > perfLog_
std::unique_ptr< HashRouter > hashRouter_
std::optional< OpenLedger > openLedger_
RCLValidations & getValidations() override
OpenLedger & openLedger() override
Resource::Manager & getResourceManager() override
NodeStoreScheduler m_nodeStoreScheduler
ClosureCounter< void, boost::system::error_code const & > waitHandlerCounter_
RelationalDatabase & getRelationalDatabase() override
TransactionMaster & getMasterTransaction() override
std::chrono::milliseconds getIOLatency() override
std::unique_ptr< CollectorManager > m_collectorManager
boost::asio::io_context & getIOContext() override
std::optional< PublicKey const > getValidationPublicKey() const override
HashRouter & getHashRouter() override
LoadManager & getLoadManager() override
PendingSaves pendingSaves_
std::atomic< bool > checkSigs_
bool checkSigs() const override
bool serverOkay(std::string &reason) override
std::unique_ptr< SHAMapStore > m_shaMapStore
Application::MutexType m_masterMutex
InboundTransactions & getInboundTransactions() override
io_latency_sampler m_io_latency_sampler
std::unique_ptr< AmendmentTable > m_amendmentTable
std::unique_ptr< InboundTransactions > m_inboundTransactions
SHAMapStore & getSHAMapStore() override
boost::asio::steady_timer sweepTimer_
std::unique_ptr< NodeStore::Database > m_nodeStore
std::unique_ptr< LoadFeeTrack > mFeeTrack
boost::asio::steady_timer entropyTimer_
std::unique_ptr< Overlay > overlay_
bool setup(boost::program_options::variables_map const &cmdline) override
bool initRelationalDatabase()
Overlay & overlay() override
std::unique_ptr< Config > config_
ManifestCache & publisherManifests() override
std::unique_ptr< ManifestCache > validatorManifests_
CollectorManager & getCollectorManager() override
std::optional< uint256 > trapTxID_
std::unique_ptr< ResolverAsio > m_resolver
NetworkOPs & getOPs() override
TimeKeeper & timeKeeper() override
std::unique_ptr< ValidatorList > validators_
std::unique_ptr< TxQ > txQ_
static std::size_t numberOfThreads(Config const &config)
OpenLedger const & openLedger() const override
std::unique_ptr< ManifestCache > publisherManifests_
LedgerIndex getMaxDisallowedLedger() override
Ensure that a newly-started validator does not sign proposals older than the last ledger it persisted...
NodeCache & getTempNodeCache() override
Application & app() override
ValidatorList & validators() override
PeerReservationTable & peerReservations() override
ApplicationImp(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
std::unique_ptr< PeerReservationTable > peerReservations_
std::unique_ptr< Resource::Manager > m_resourceManager
std::pair< PublicKey, SecretKey > const & nodeIdentity() override
std::unique_ptr< Logs > logs_
std::unique_ptr< DatabaseCon > mWalletDB
CachedSLEs & cachedSLEs() override
ValidatorSite & validatorSites() override
virtual std::optional< uint256 > const & trapTxID() const override
std::atomic_flag isTimeToStop
std::optional< SQLiteDatabase > relationalDatabase_
std::unique_ptr< LedgerMaster > m_ledgerMaster
std::unique_ptr< GRPCServer > grpcServer_
std::unique_ptr< ServerHandler > serverHandler_
ValidatorKeys const validatorKeys_
std::uint64_t instanceID() const override
Returns a 64-bit instance identifier, generated at startup.
OrderBookDB & getOrderBookDB() override
Family & getNodeFamily() override
void gotTXSet(std::shared_ptr< SHAMap > const &set, bool fromAcquire)
Config & config() override
DatabaseCon & getWalletDB() override
Retrieve the "wallet database".
PathRequests & getPathRequests() override
bool isStopping() const override
std::unique_ptr< TimeKeeper > timeKeeper_
beast::Journal journal(std::string const &name) override
std::unique_ptr< ValidatorSite > validatorSites_
RCLValidations mValidations
void signalStop(std::string msg) override
std::uint64_t const instanceCookie_
LedgerCleaner & getLedgerCleaner() override
ManifestCache & validatorManifests() override
AmendmentTable & getAmendmentTable() override
int fdRequired() const override
TaggedCache< uint256, AcceptedLedger > m_acceptedLedgerCache
std::unique_ptr< PathRequests > m_pathRequests
std::unique_ptr< JobQueue > m_jobQueue
LedgerMaster & getLedgerMaster() override
NodeStore::Database & getNodeStore() override
std::unique_ptr< OrderBookDB > m_orderBookDB
TransactionMaster m_txMaster
std::unique_ptr< Cluster > cluster_
std::unique_ptr< NetworkOPs > m_networkOPs
virtual ServerHandler & getServerHandler() override
JobQueue & getJobQueue() override
PendingSaves & pendingSaves() override
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
std::unique_ptr< InboundLedgers > m_inboundLedgers
TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache() override
perf::PerfLog & getPerfLog() override
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.
Tracks order books in the ledger.
Manages the set of connected peers.
Keeps track of which ledgers haven't been fully saved.
static std::unique_ptr< ResolverAsio > New(boost::asio::io_context &, beast::Journal)
An endpoint that consumes resources.
Tracks load and resource consumption.
class to create database, launch online delete thread, and related SQLite database
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
Holds a collection of configuration values.
std::size_t size() const
Returns the number of items in the container.
Manages various times used by the server.
Validator keys and manifest as set in configuration file.
std::optional< Keys > keys
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Singleton class that maintains performance counters and optionally writes Json-formatted data to a di...
T hardware_concurrency(T... args)
A namespace for easy access to logging severity values.
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
std::unique_ptr< Manager > make_Manager(beast::insight::Collector::ptr const &collector, beast::Journal journal)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
std::unique_ptr< LedgerCleaner > make_LedgerCleaner(Application &app, beast::Journal journal)
std::unique_ptr< LoadManager > make_LoadManager(Application &app, beast::Journal journal)
Stopwatch & stopwatch()
Returns an instance of a wall clock.
TxQ::Setup setup_TxQ(Config const &config)
Build a TxQ::Setup object from application configuration.
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
create_genesis_t const create_genesis
HashRouter::Setup setup_HashRouter(Config const &config)
Create HashRouter setup from configuration.
std::pair< PublicKey, SecretKey > getNodeIdentity(soci::session &session)
Returns a stable public and private key for this node.
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
std::unique_ptr< SHAMapStore > make_SHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
std::unique_ptr< AmendmentTable > make_AmendmentTable(ServiceRegistry ®istry, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
std::unique_ptr< NetworkOPs > make_NetworkOPs(ServiceRegistry ®istry, NetworkOPs::clock_type &clock, bool standalone, std::size_t minPeerCount, bool start_valid, JobQueue &job_queue, LedgerMaster &ledgerMaster, ValidatorKeys const &validatorKeys, boost::asio::io_context &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
std::unique_ptr< CollectorManager > make_CollectorManager(Section const ¶ms, beast::Journal journal)
std::unique_ptr< InboundLedgers > make_InboundLedgers(Application &app, InboundLedgers::clock_type &clock, beast::insight::Collector::ptr const &collector)
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_context &io_context, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
constexpr auto megabytes(T value) noexcept
static void fixConfigPorts(Config &config, Endpoints const &endpoints)
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
void addJson(Json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a Json::Value with a description of the ledger.
Overlay::Setup setup_Overlay(BasicConfig const &config)
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
std::unordered_map< std::string, boost::asio::ip::tcp::endpoint > Endpoints
std::optional< uint256 > getRegisteredFeature(std::string const &name)
std::unique_ptr< OrderBookDB > make_OrderBookDB(ServiceRegistry ®istry, OrderBookDBConfig const &config)
Create an OrderBookDB instance.
SQLiteDatabase setup_RelationalDatabase(ServiceRegistry ®istry, Config const &config, JobQueue &jobQueue)
setup_RelationalDatabase Creates and returns a SQLiteDatabase instance based on configuration.
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
std::unique_ptr< Overlay > make_Overlay(Application &app, Overlay::Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_context &io_context, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
Creates the implementation of Overlay.
static std::string importNodeDatabase()