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
248 perf::setup_PerfLog(
config_->section(
"perf"),
config_->CONFIG_DIR),
281 logs_->journal(
"JobQueue"),
311 logs_->journal(
"LedgerMaster")))
332 logs_->journal(
"TaggedCache"))
344 logs_->journal(
"NetworkOPs"),
360 config_->legacy(
"database_path"),
361 logs_->journal(
"ValidatorList"),
396 logs_->journal(
"Application"),
426 setup(boost::program_options::variables_map
const& cmdline)
override;
428 start(
bool withTimers)
override;
492 LogicError(
"Accessing Application::nodeIdentity() before it is initialized.");
515 "xrpl::ApplicationImp::getServerHandler : non-null server "
520 boost::asio::io_context&
722 XRPL_ASSERT(
overlay_,
"xrpl::ApplicationImp::overlay : non-null overlay");
729 XRPL_ASSERT(
txQ_,
"xrpl::ApplicationImp::getTxQ : non-null transaction queue");
738 "xrpl::ApplicationImp::getRelationalDatabase : non-null "
739 "relational database");
746 XRPL_ASSERT(
mWalletDB,
"xrpl::ApplicationImp::getWalletDB : non-null wallet database");
763 "xrpl::ApplicationImp::initRelationalDatabase : null wallet "
772 setup.useGlobalPragma =
false;
790 auto j =
logs_->journal(
"NodeObject");
799 JLOG(j.warn()) <<
"Starting node import from '" << source->getName() <<
"' to '" <<
m_nodeStore->getName()
803 auto const start = steady_clock::now();
807 auto const elapsed = duration_cast<seconds>(steady_clock::now() -
start);
808 JLOG(j.warn()) <<
"Node import from '" << source->getName() <<
"' took " << elapsed.count() <<
" seconds.";
830 if (
auto optionalCountedHandler =
waitHandlerCounter_.wrap([
this](boost::system::error_code
const& e) {
831 if (e.value() == boost::system::errc::success)
833 m_jobQueue->addJob(jtSWEEP,
"sweep", [this]() { doSweep(); });
836 if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted)
839 JLOG(m_journal.error()) <<
"Sweep timer got error '" << e.message() <<
"'. Restarting timer.";
847 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
855 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap([
this](boost::system::error_code
const& e) {
856 if (e.value() == boost::system::errc::success)
858 crypto_prng().mix_entropy();
862 if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted)
865 JLOG(m_journal.error()) <<
"Entropy timer got error '" << e.message() <<
"'. Restarting timer.";
870 using namespace std::chrono_literals;
871 entropyTimer_.expires_after(5min);
872 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
879 XRPL_ASSERT(relationalDatabase_,
"xrpl::ApplicationImp::doSweep : non-null relational database");
880 if (!config_->standalone() && !relationalDatabase_->transactionDbHasSpace(*config_))
882 signalStop(
"Out of transaction DB space");
894 std::size_t const oldFullBelowSize = fullBelowCache->size();
895 std::size_t const oldTreeNodeSize = treeNodeCache->size();
899 JLOG(m_journal.debug()) <<
"NodeFamily::FullBelowCache sweep. Size before: " << oldFullBelowSize
900 <<
"; size after: " << fullBelowCache->size();
902 JLOG(m_journal.debug()) <<
"NodeFamily::TreeNodeCache sweep. Size before: " << oldTreeNodeSize
903 <<
"; size after: " << treeNodeCache->size();
910 getMasterTransaction().sweep();
912 JLOG(m_journal.debug()) <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
913 <<
"; size after: " << masterTxCache.
size();
916 std::size_t const oldLedgerMasterCacheSize = getLedgerMaster().getFetchPackCacheSize();
918 getLedgerMaster().sweep();
920 JLOG(m_journal.debug()) <<
"LedgerMaster sweep. Size before: " << oldLedgerMasterCacheSize
921 <<
"; size after: " << getLedgerMaster().getFetchPackCacheSize();
925 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
927 getTempNodeCache().sweep();
929 JLOG(m_journal.debug()) <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
930 <<
"; size after: " << getTempNodeCache().size();
933 std::size_t const oldCurrentCacheSize = getValidations().sizeOfCurrentCache();
934 std::size_t const oldSizeSeqEnforcesSize = getValidations().sizeOfSeqEnforcersCache();
935 std::size_t const oldByLedgerSize = getValidations().sizeOfByLedgerCache();
936 std::size_t const oldBySequenceSize = getValidations().sizeOfBySequenceCache();
938 getValidations().expire(m_journal);
940 JLOG(m_journal.debug()) <<
"Validations Current expire. Size before: " << oldCurrentCacheSize
941 <<
"; size after: " << getValidations().sizeOfCurrentCache();
943 JLOG(m_journal.debug()) <<
"Validations SeqEnforcer expire. Size before: " << oldSizeSeqEnforcesSize
944 <<
"; size after: " << getValidations().sizeOfSeqEnforcersCache();
946 JLOG(m_journal.debug()) <<
"Validations ByLedger expire. Size before: " << oldByLedgerSize
947 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
949 JLOG(m_journal.debug()) <<
"Validations BySequence expire. Size before: " << oldBySequenceSize
950 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
953 std::size_t const oldInboundLedgersSize = getInboundLedgers().cacheSize();
955 getInboundLedgers().sweep();
957 JLOG(m_journal.debug()) <<
"InboundLedgers sweep. Size before: " << oldInboundLedgersSize
958 <<
"; size after: " << getInboundLedgers().cacheSize();
961 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
962 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
963 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
965 getLedgerReplayer().sweep();
967 JLOG(m_journal.debug()) <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
968 <<
"; size after: " << getLedgerReplayer().tasksSize();
970 JLOG(m_journal.debug()) <<
"LedgerReplayer deltas sweep. Size before: " << oldDeltasSize
971 <<
"; size after: " << getLedgerReplayer().deltasSize();
973 JLOG(m_journal.debug()) <<
"LedgerReplayer skipLists sweep. Size before: " << oldSkipListsSize
974 <<
"; size after: " << getLedgerReplayer().skipListsSize();
977 std::size_t const oldAcceptedLedgerSize = m_acceptedLedgerCache.size();
979 m_acceptedLedgerCache.sweep();
981 JLOG(m_journal.debug()) <<
"AcceptedLedgerCache sweep. Size before: " << oldAcceptedLedgerSize
982 <<
"; size after: " << m_acceptedLedgerCache.size();
985 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
989 JLOG(m_journal.debug()) <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
990 <<
"; size after: " << cachedSLEs_.size();
1000 return maxDisallowedLedger_;
1015 startGenesisLedger();
1018 getLastFullLedger();
1027 setMaxDisallowedLedger();
1040ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1050 m_signals.
add(SIGINT);
1051 m_signals.add(SIGTERM);
1052 m_signals.async_wait([
this](boost::system::error_code
const& ec,
int signum) {
1054 if (ec == boost::asio::error::operation_aborted)
1057 JLOG(m_journal.info()) <<
"Received signal " << signum;
1059 if (signum == SIGTERM || signum == SIGINT)
1060 signalStop(
"Signal: " + to_string(signum));
1063 auto debug_log = config_->getDebugLogFile();
1065 if (!debug_log.empty())
1070 if (!logs_->open(debug_log))
1071 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1074 if (logs_->threshold() > kDebug)
1075 logs_->threshold(kDebug);
1078 JLOG(m_journal.info()) <<
"Process starting: " << BuildInfo::getFullVersionString()
1079 <<
", Instance Cookie: " << instanceCookie_;
1081 if (numberOfThreads(*config_) < 2)
1083 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1084 "system configuration.";
1088 logs_->silent(config_->silent());
1090 if (!initRelationalDatabase() || !initNodeStore())
1093 if (!peerReservations_->load(getWalletDB()))
1095 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1099 if (validatorKeys_.keys)
1100 setMaxDisallowedLedger();
1104 auto const supported = []() {
1105 auto const& amendments = detail::supportedAmendments();
1107 supported.reserve(amendments.size());
1108 for (
auto const& [a, vote] : amendments)
1111 XRPL_ASSERT(f,
"xrpl::ApplicationImp::setup : registered feature");
1113 supported.emplace_back(a, *f, vote);
1117 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1119 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1122 *
this, config().AMENDMENT_MAJORITY_TIME, supported, upVoted, downVoted, logs_->journal(
"Amendments"));
1125 Pathfinder::initPathTable();
1127 auto const startUp = config_->START_UP;
1128 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1129 if (startUp == StartUpType::FRESH)
1131 JLOG(m_journal.info()) <<
"Starting new Ledger";
1133 startGenesisLedger();
1135 else if (startUp == StartUpType::LOAD || startUp == StartUpType::LOAD_FILE || startUp == StartUpType::REPLAY)
1137 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1140 config_->START_LEDGER,
1141 startUp == StartUpType::REPLAY,
1142 startUp == StartUpType::LOAD_FILE,
1143 config_->TRAP_TX_HASH))
1145 JLOG(m_journal.error()) <<
"The specified ledger could not be loaded.";
1146 if (config_->FAST_LOAD)
1150 startGenesisLedger();
1158 else if (startUp == StartUpType::NETWORK)
1162 if (!config_->standalone())
1163 m_networkOPs->setNeedNetworkLedger();
1165 startGenesisLedger();
1169 startGenesisLedger();
1172 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1174 m_ledgerMaster->setLedgerRangePresent(forcedRange->first, forcedRange->second);
1177 m_orderBookDB->setup(getLedgerMaster().getCurrentLedger());
1181 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1183 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1188 if (validatorKeys_.configInvalid())
1191 if (!validatorManifests_->load(
1193 "ValidatorManifests",
1194 validatorKeys_.manifest,
1195 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1197 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1201 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1210 if (validatorKeys_.keys)
1211 localSigningKey = validatorKeys_.keys->publicKey;
1214 if (!validators_->load(
1216 config().section(SECTION_VALIDATORS).values(),
1217 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1218 config().VALIDATOR_LIST_THRESHOLD))
1220 JLOG(m_journal.fatal()) <<
"Invalid entry in validator configuration.";
1225 if (!validatorSites_->load(config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1227 JLOG(m_journal.fatal()) <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1232 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1253 m_collectorManager->collector());
1257 if (!m_networkOPs->beginConsensus(m_ledgerMaster->getClosedLedger()->header().hash, {}))
1259 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1268 serverHandler_->setup(setup, m_journal);
1273 if (
auto stream = m_journal.fatal())
1275 stream <<
"Unable to setup server handler";
1277 stream <<
": " << e.
what();
1284 if (!config_->standalone())
1288 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1290 JLOG(m_journal.warn()) <<
"No outbound peer connections will be made";
1295 m_networkOPs->setStateTimer();
1299 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1301 m_networkOPs->setStandAlone();
1304 if (config_->canSign())
1306 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1307 "'sign' and 'sign_for'";
1308 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1309 "implications and have";
1310 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1311 "in a future release of";
1312 JLOG(m_journal.warn()) <<
"*** rippled.";
1313 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1314 "transactions please edit your";
1315 JLOG(m_journal.warn()) <<
"*** configuration file and remove the [enable_signing] stanza.";
1316 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1317 "please migrate to a";
1318 JLOG(m_journal.warn()) <<
"*** standalone signing solution as soon as possible.";
1324 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1329 if (!jrReader.
parse(cmd, jvCommand))
1331 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in [" << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1334 if (!config_->quiet())
1336 JLOG(m_journal.fatal()) <<
"Startup RPC: " << jvCommand <<
std::endl;
1342 {journal(
"RPCHandler"),
1351 RPC::apiMaximumSupportedVersion},
1355 RPC::doCommand(context, jvResult);
1357 if (!config_->quiet())
1359 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1363 validatorSites_->start();
1369ApplicationImp::start(
bool withTimers)
1371 JLOG(m_journal.info()) <<
"Application starting. Version is " << BuildInfo::getVersionString();
1379 m_io_latency_sampler.start();
1380 m_resolver->start();
1381 m_loadManager->start();
1382 m_shaMapStore->start();
1386 if (grpcServer_->start())
1387 fixConfigPorts(*config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1389 ledgerCleaner_->start();
1394ApplicationImp::run()
1396 if (!config_->standalone())
1402 getLoadManager().activateStallDetector();
1407 JLOG(m_journal.debug()) <<
"Application stopping";
1409 m_io_latency_sampler.cancel_async();
1417 m_io_latency_sampler.cancel();
1419 m_resolver->stop_async();
1429 sweepTimer_.cancel();
1431 catch (boost::system::system_error
const& e)
1433 JLOG(m_journal.error()) <<
"Application: sweepTimer cancel error: " << e.what();
1438 entropyTimer_.cancel();
1440 catch (boost::system::system_error
const& e)
1442 JLOG(m_journal.error()) <<
"Application: entropyTimer cancel error: " << e.what();
1448 using namespace std::chrono_literals;
1450 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1452 mValidations.flush();
1454 validatorSites_->stop();
1457 validatorManifests_->save(
1458 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
return validators().listed(pubKey); });
1460 publisherManifests_->save(getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1461 return validators().trustedPublisher(pubKey);
1466 m_loadManager->stop();
1467 m_shaMapStore->stop();
1471 grpcServer_->stop();
1472 m_networkOPs->stop();
1473 serverHandler_->stop();
1474 m_ledgerReplayer->stop();
1475 m_inboundTransactions->stop();
1476 m_inboundLedgers->stop();
1477 ledgerCleaner_->stop();
1478 m_nodeStore->stop();
1481 JLOG(m_journal.info()) <<
"Done.";
1490 JLOG(m_journal.warn()) <<
"Server stopping";
1492 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1494 isTimeToStop.notify_all();
1499ApplicationImp::checkSigs()
const
1505ApplicationImp::checkSigs(
bool check)
1511ApplicationImp::isStopping()
const
1517ApplicationImp::fdRequired()
const
1524 needed += 2 * overlay_->limit();
1528 needed +=
std::max(5, m_shaMapStore->fdRequired());
1532 for (
auto const& p : serverHandler_->setup().ports)
1542ApplicationImp::startGenesisLedger()
1545 (config_->START_UP == StartUpType::FRESH) ? m_amendmentTable->getDesired() :
std::vector<uint256>{};
1549 m_ledgerMaster->storeLedger(genesis);
1552 next->updateSkipList();
1554 next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()),
1555 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1556 next->setImmutable();
1557 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1558 m_ledgerMaster->storeLedger(next);
1559 m_ledgerMaster->switchLCL(next);
1563ApplicationImp::getLastFullLedger()
1565 auto j = journal(
"Ledger");
1575 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
1576 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1577 ledger->setImmutable();
1579 if (getLedgerMaster().haveLedger(seq))
1580 ledger->setValidated();
1582 if (ledger->header().hash ==
hash)
1584 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1588 if (
auto stream = j.error())
1590 stream <<
"Failed on ledger";
1592 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1600 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1614 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1621 if (!reader.
parse(ledgerFile, jLedger))
1623 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1630 if (ledger.
get().isMember(
"result"))
1631 ledger = ledger.
get()[
"result"];
1633 if (ledger.
get().isMember(
"ledger"))
1634 ledger = ledger.
get()[
"ledger"];
1637 auto closeTime = timeKeeper().closeTime();
1638 using namespace std::chrono_literals;
1639 auto closeTimeResolution = 30s;
1640 bool closeTimeEstimated =
false;
1643 if (ledger.
get().isMember(
"accountState"))
1645 if (ledger.
get().isMember(jss::ledger_index))
1647 seq = ledger.
get()[jss::ledger_index].asUInt();
1650 if (ledger.
get().isMember(
"close_time"))
1653 using d = tp::duration;
1654 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1656 if (ledger.
get().isMember(
"close_time_resolution"))
1659 closeTimeResolution =
seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1661 if (ledger.
get().isMember(
"close_time_estimated"))
1663 closeTimeEstimated = ledger.
get()[
"close_time_estimated"].asBool();
1665 if (ledger.
get().isMember(
"total_coins"))
1667 totalDrops = beast::lexicalCastThrow<std::uint64_t>(ledger.
get()[
"total_coins"].asString());
1670 ledger = ledger.
get()[
"accountState"];
1673 if (!ledger.
get().isArrayOrNull())
1675 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1680 loadLedger->setTotalDrops(totalDrops);
1682 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1688 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1696 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1706 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1714 if (!loadLedger->addSLE(sle))
1716 JLOG(m_journal.fatal()) <<
"Couldn't add serialized ledger: " << uIndex;
1724 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()),
1725 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1726 loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated);
1732 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1738ApplicationImp::loadOldLedger(
1750 if (!ledgerID.
empty())
1751 loadLedger = loadLedgerFromFile(ledgerID);
1753 else if (ledgerID.
length() == 64)
1757 if (
hash.parseHex(ledgerID))
1766 if (il->checkLocal())
1767 loadLedger = il->getLedger();
1771 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1773 loadLedger = getLastFullLedger();
1792 replayLedger = loadLedger;
1794 JLOG(m_journal.info()) <<
"Loading parent ledger";
1796 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1799 JLOG(m_journal.info()) <<
"Loading parent ledger from node store";
1804 replayLedger->header().parentHash,
1806 InboundLedger::Reason::GENERIC,
1810 if (il->checkLocal())
1811 loadLedger = il->getLedger();
1816 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1818 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1825 using namespace std::chrono_literals;
1826 using namespace date;
1829 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1831 JLOG(m_journal.fatal()) <<
"\n\n*** WARNING ***\n"
1832 "You are replaying a ledger from before "
1833 << to_string(ledgerWarnTimePoint)
1835 "This replay will not handle your ledger as it was "
1837 "handled.\nConsider running an earlier version of rippled "
1839 "get the older rules.\n*** CONTINUING ***\n";
1842 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash <<
" seq:" << loadLedger->header().seq;
1844 if (loadLedger->header().accountHash.isZero())
1847 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
1848 UNREACHABLE(
"xrpl::ApplicationImp::loadOldLedger : ledger is empty");
1853 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
1856 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
1858 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
1864 if (!loadLedger->assertSensible(journal(
"Ledger")))
1867 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
1869 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
1875 m_ledgerMaster->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq);
1877 m_ledgerMaster->switchLCL(loadLedger);
1878 loadLedger->setValidated();
1879 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
1880 openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
1888 for (
auto const& [_, tx] : replayData->orderedTxns())
1891 auto txID = tx->getTransactionID();
1892 if (trapTxID == txID)
1895 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
1901 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
1909 m_ledgerMaster->takeReplay(std::move(replayData));
1911 if (trapTxID && !trapTxID_)
1913 JLOG(m_journal.fatal()) <<
"Ledger " << replayLedger->header().seq
1914 <<
" does not contain the transaction hash " << *trapTxID;
1921 JLOG(m_journal.fatal()) <<
"While loading specified ledger: " << mn.
what();
1924 catch (boost::bad_lexical_cast&)
1926 JLOG(m_journal.fatal()) <<
"Ledger specified '" << ledgerID <<
"' is not valid";
1936 if (!config().ELB_SUPPORT)
1941 reason =
"Server is shutting down";
1945 if (getOPs().isNeedNetworkLedger())
1947 reason =
"Not synchronized with network yet";
1951 if (getOPs().isAmendmentBlocked())
1953 reason =
"Server version too old";
1957 if (getOPs().isUNLBlocked())
1959 reason =
"No valid validator list available";
1963 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
1965 reason =
"Not synchronized with network";
1969 if (!getLedgerMaster().isCaughtUp(reason))
1972 if (getFeeTrack().isLoadedLocal())
1974 reason =
"Too much load";
1984 return logs_->journal(name);
1988ApplicationImp::setMaxDisallowedLedger()
1990 auto seq = getRelationalDatabase().getMaxLedgerSeq();
1992 maxDisallowedLedger_ = *seq;
1994 JLOG(m_journal.trace()) <<
"Max persisted ledger is " << maxDisallowedLedger_;
2014 for (
auto const& [name, ep] : endpoints)
2016 if (!config.
exists(name))
2019 auto& section = config[name];
2020 auto const optPort = section.get(
"port");
2023 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()