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/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/HashRouter.h>
20#include <xrpld/app/misc/LoadFeeTrack.h>
21#include <xrpld/app/misc/NetworkOPs.h>
22#include <xrpld/app/misc/SHAMapStore.h>
23#include <xrpld/app/misc/TxQ.h>
24#include <xrpld/app/misc/ValidatorKeys.h>
25#include <xrpld/app/misc/ValidatorSite.h>
26#include <xrpld/app/paths/PathRequests.h>
27#include <xrpld/app/rdb/RelationalDatabase.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/PeerReservationTable.h>
40#include <xrpl/core/PerfLog.h>
41#include <xrpl/crypto/csprng.h>
42#include <xrpl/json/json_reader.h>
43#include <xrpl/nodestore/DummyScheduler.h>
44#include <xrpl/protocol/ApiVersion.h>
45#include <xrpl/protocol/BuildInfo.h>
46#include <xrpl/protocol/Feature.h>
47#include <xrpl/protocol/Protocol.h>
48#include <xrpl/protocol/STParsedJSON.h>
49#include <xrpl/rdb/DatabaseCon.h>
50#include <xrpl/resource/Fees.h>
51#include <xrpl/server/Wallet.h>
53#include <boost/algorithm/string/predicate.hpp>
54#include <boost/asio/steady_timer.hpp>
55#include <boost/system/error_code.hpp>
90 boost::asio::io_context& ios)
101 template <
class Duration>
106 auto const lastSample = ceil<milliseconds>(elapsed);
110 if (lastSample >= 10ms)
112 if (lastSample >= 500ms)
114 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"),
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 if (!config_->standalone() && !getRelationalDatabase().transactionDbHasSpace(*config_))
877 signalStop(
"Out of transaction DB space");
889 std::size_t const oldFullBelowSize = fullBelowCache->size();
890 std::size_t const oldTreeNodeSize = treeNodeCache->size();
894 JLOG(m_journal.debug()) <<
"NodeFamily::FullBelowCache sweep. Size before: " << oldFullBelowSize
895 <<
"; size after: " << fullBelowCache->size();
897 JLOG(m_journal.debug()) <<
"NodeFamily::TreeNodeCache sweep. Size before: " << oldTreeNodeSize
898 <<
"; size after: " << treeNodeCache->size();
905 getMasterTransaction().sweep();
907 JLOG(m_journal.debug()) <<
"MasterTransaction sweep. Size before: " << oldMasterTxSize
908 <<
"; size after: " << masterTxCache.
size();
911 std::size_t const oldLedgerMasterCacheSize = getLedgerMaster().getFetchPackCacheSize();
913 getLedgerMaster().sweep();
915 JLOG(m_journal.debug()) <<
"LedgerMaster sweep. Size before: " << oldLedgerMasterCacheSize
916 <<
"; size after: " << getLedgerMaster().getFetchPackCacheSize();
920 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
922 getTempNodeCache().sweep();
924 JLOG(m_journal.debug()) <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
925 <<
"; size after: " << getTempNodeCache().size();
928 std::size_t const oldCurrentCacheSize = getValidations().sizeOfCurrentCache();
929 std::size_t const oldSizeSeqEnforcesSize = getValidations().sizeOfSeqEnforcersCache();
930 std::size_t const oldByLedgerSize = getValidations().sizeOfByLedgerCache();
931 std::size_t const oldBySequenceSize = getValidations().sizeOfBySequenceCache();
933 getValidations().expire(m_journal);
935 JLOG(m_journal.debug()) <<
"Validations Current expire. Size before: " << oldCurrentCacheSize
936 <<
"; size after: " << getValidations().sizeOfCurrentCache();
938 JLOG(m_journal.debug()) <<
"Validations SeqEnforcer expire. Size before: " << oldSizeSeqEnforcesSize
939 <<
"; size after: " << getValidations().sizeOfSeqEnforcersCache();
941 JLOG(m_journal.debug()) <<
"Validations ByLedger expire. Size before: " << oldByLedgerSize
942 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
944 JLOG(m_journal.debug()) <<
"Validations BySequence expire. Size before: " << oldBySequenceSize
945 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
948 std::size_t const oldInboundLedgersSize = getInboundLedgers().cacheSize();
950 getInboundLedgers().sweep();
952 JLOG(m_journal.debug()) <<
"InboundLedgers sweep. Size before: " << oldInboundLedgersSize
953 <<
"; size after: " << getInboundLedgers().cacheSize();
956 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
957 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
958 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
960 getLedgerReplayer().sweep();
962 JLOG(m_journal.debug()) <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
963 <<
"; size after: " << getLedgerReplayer().tasksSize();
965 JLOG(m_journal.debug()) <<
"LedgerReplayer deltas sweep. Size before: " << oldDeltasSize
966 <<
"; size after: " << getLedgerReplayer().deltasSize();
968 JLOG(m_journal.debug()) <<
"LedgerReplayer skipLists sweep. Size before: " << oldSkipListsSize
969 <<
"; size after: " << getLedgerReplayer().skipListsSize();
972 std::size_t const oldAcceptedLedgerSize = m_acceptedLedgerCache.size();
974 m_acceptedLedgerCache.sweep();
976 JLOG(m_journal.debug()) <<
"AcceptedLedgerCache sweep. Size before: " << oldAcceptedLedgerSize
977 <<
"; size after: " << m_acceptedLedgerCache.size();
980 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
984 JLOG(m_journal.debug()) <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
985 <<
"; size after: " << cachedSLEs_.size();
995 return maxDisallowedLedger_;
1010 startGenesisLedger();
1013 getLastFullLedger();
1022 setMaxDisallowedLedger();
1035ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1045 m_signals.
add(SIGINT);
1046 m_signals.add(SIGTERM);
1047 m_signals.async_wait([
this](boost::system::error_code
const& ec,
int signum) {
1049 if (ec == boost::asio::error::operation_aborted)
1052 JLOG(m_journal.info()) <<
"Received signal " << signum;
1054 if (signum == SIGTERM || signum == SIGINT)
1055 signalStop(
"Signal: " + to_string(signum));
1058 auto debug_log = config_->getDebugLogFile();
1060 if (!debug_log.empty())
1065 if (!logs_->open(debug_log))
1066 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1069 if (logs_->threshold() > kDebug)
1070 logs_->threshold(kDebug);
1073 JLOG(m_journal.info()) <<
"Process starting: " << BuildInfo::getFullVersionString()
1074 <<
", Instance Cookie: " << instanceCookie_;
1076 if (numberOfThreads(*config_) < 2)
1078 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1079 "system configuration.";
1083 logs_->silent(config_->silent());
1085 if (!initRelationalDatabase() || !initNodeStore())
1088 if (!peerReservations_->load(getWalletDB()))
1090 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1094 if (validatorKeys_.keys)
1095 setMaxDisallowedLedger();
1099 auto const supported = []() {
1100 auto const& amendments = detail::supportedAmendments();
1102 supported.reserve(amendments.size());
1103 for (
auto const& [a, vote] : amendments)
1106 XRPL_ASSERT(f,
"xrpl::ApplicationImp::setup : registered feature");
1108 supported.emplace_back(a, *f, vote);
1112 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1114 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1117 *
this, config().AMENDMENT_MAJORITY_TIME, supported, upVoted, downVoted, logs_->journal(
"Amendments"));
1120 Pathfinder::initPathTable();
1122 auto const startUp = config_->START_UP;
1123 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1124 if (startUp == StartUpType::FRESH)
1126 JLOG(m_journal.info()) <<
"Starting new Ledger";
1128 startGenesisLedger();
1130 else if (startUp == StartUpType::LOAD || startUp == StartUpType::LOAD_FILE || startUp == StartUpType::REPLAY)
1132 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1135 config_->START_LEDGER,
1136 startUp == StartUpType::REPLAY,
1137 startUp == StartUpType::LOAD_FILE,
1138 config_->TRAP_TX_HASH))
1140 JLOG(m_journal.error()) <<
"The specified ledger could not be loaded.";
1141 if (config_->FAST_LOAD)
1145 startGenesisLedger();
1153 else if (startUp == StartUpType::NETWORK)
1157 if (!config_->standalone())
1158 m_networkOPs->setNeedNetworkLedger();
1160 startGenesisLedger();
1164 startGenesisLedger();
1167 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1169 m_ledgerMaster->setLedgerRangePresent(forcedRange->first, forcedRange->second);
1172 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1176 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1178 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1183 if (validatorKeys_.configInvalid())
1186 if (!validatorManifests_->load(
1188 "ValidatorManifests",
1189 validatorKeys_.manifest,
1190 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1192 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1196 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1205 if (validatorKeys_.keys)
1206 localSigningKey = validatorKeys_.keys->publicKey;
1209 if (!validators_->load(
1211 config().section(SECTION_VALIDATORS).values(),
1212 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1213 config().VALIDATOR_LIST_THRESHOLD))
1215 JLOG(m_journal.fatal()) <<
"Invalid entry in validator configuration.";
1220 if (!validatorSites_->load(config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1222 JLOG(m_journal.fatal()) <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1227 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1248 m_collectorManager->collector());
1252 if (!m_networkOPs->beginConsensus(m_ledgerMaster->getClosedLedger()->header().hash, {}))
1254 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1263 serverHandler_->setup(setup, m_journal);
1268 if (
auto stream = m_journal.fatal())
1270 stream <<
"Unable to setup server handler";
1272 stream <<
": " << e.
what();
1279 if (!config_->standalone())
1283 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1285 JLOG(m_journal.warn()) <<
"No outbound peer connections will be made";
1290 m_networkOPs->setStateTimer();
1294 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1296 m_networkOPs->setStandAlone();
1299 if (config_->canSign())
1301 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1302 "'sign' and 'sign_for'";
1303 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1304 "implications and have";
1305 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1306 "in a future release of";
1307 JLOG(m_journal.warn()) <<
"*** rippled.";
1308 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1309 "transactions please edit your";
1310 JLOG(m_journal.warn()) <<
"*** configuration file and remove the [enable_signing] stanza.";
1311 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1312 "please migrate to a";
1313 JLOG(m_journal.warn()) <<
"*** standalone signing solution as soon as possible.";
1319 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1324 if (!jrReader.
parse(cmd, jvCommand))
1326 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in [" << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1329 if (!config_->quiet())
1331 JLOG(m_journal.fatal()) <<
"Startup RPC: " << jvCommand <<
std::endl;
1337 {journal(
"RPCHandler"),
1346 RPC::apiMaximumSupportedVersion},
1350 RPC::doCommand(context, jvResult);
1352 if (!config_->quiet())
1354 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1358 validatorSites_->start();
1364ApplicationImp::start(
bool withTimers)
1366 JLOG(m_journal.info()) <<
"Application starting. Version is " << BuildInfo::getVersionString();
1374 m_io_latency_sampler.start();
1375 m_resolver->start();
1376 m_loadManager->start();
1377 m_shaMapStore->start();
1381 if (grpcServer_->start())
1382 fixConfigPorts(*config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1384 ledgerCleaner_->start();
1389ApplicationImp::run()
1391 if (!config_->standalone())
1397 getLoadManager().activateStallDetector();
1402 JLOG(m_journal.debug()) <<
"Application stopping";
1404 m_io_latency_sampler.cancel_async();
1412 m_io_latency_sampler.cancel();
1414 m_resolver->stop_async();
1424 sweepTimer_.cancel();
1426 catch (boost::system::system_error
const& e)
1428 JLOG(m_journal.error()) <<
"Application: sweepTimer cancel error: " << e.what();
1433 entropyTimer_.cancel();
1435 catch (boost::system::system_error
const& e)
1437 JLOG(m_journal.error()) <<
"Application: entropyTimer cancel error: " << e.what();
1443 using namespace std::chrono_literals;
1445 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1447 mValidations.flush();
1449 validatorSites_->stop();
1452 validatorManifests_->save(
1453 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
return validators().listed(pubKey); });
1455 publisherManifests_->save(getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1456 return validators().trustedPublisher(pubKey);
1461 m_loadManager->stop();
1462 m_shaMapStore->stop();
1466 grpcServer_->stop();
1467 m_networkOPs->stop();
1468 serverHandler_->stop();
1469 m_ledgerReplayer->stop();
1470 m_inboundTransactions->stop();
1471 m_inboundLedgers->stop();
1472 ledgerCleaner_->stop();
1473 m_nodeStore->stop();
1476 JLOG(m_journal.info()) <<
"Done.";
1485 JLOG(m_journal.warn()) <<
"Server stopping";
1487 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1489 isTimeToStop.notify_all();
1494ApplicationImp::checkSigs()
const
1500ApplicationImp::checkSigs(
bool check)
1506ApplicationImp::isStopping()
const
1512ApplicationImp::fdRequired()
const
1519 needed += 2 * overlay_->limit();
1523 needed +=
std::max(5, m_shaMapStore->fdRequired());
1527 for (
auto const& p : serverHandler_->setup().ports)
1537ApplicationImp::startGenesisLedger()
1540 (config_->START_UP == StartUpType::FRESH) ? m_amendmentTable->getDesired() :
std::vector<uint256>{};
1544 m_ledgerMaster->storeLedger(genesis);
1547 next->updateSkipList();
1549 next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()),
1550 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1551 next->setImmutable();
1552 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1553 m_ledgerMaster->storeLedger(next);
1554 m_ledgerMaster->switchLCL(next);
1558ApplicationImp::getLastFullLedger()
1560 auto j = journal(
"Ledger");
1570 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
1571 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1572 ledger->setImmutable();
1574 if (getLedgerMaster().haveLedger(seq))
1575 ledger->setValidated();
1577 if (ledger->header().hash ==
hash)
1579 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1583 if (
auto stream = j.error())
1585 stream <<
"Failed on ledger";
1587 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1595 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1609 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1616 if (!reader.
parse(ledgerFile, jLedger))
1618 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1625 if (ledger.
get().isMember(
"result"))
1626 ledger = ledger.
get()[
"result"];
1628 if (ledger.
get().isMember(
"ledger"))
1629 ledger = ledger.
get()[
"ledger"];
1632 auto closeTime = timeKeeper().closeTime();
1633 using namespace std::chrono_literals;
1634 auto closeTimeResolution = 30s;
1635 bool closeTimeEstimated =
false;
1638 if (ledger.
get().isMember(
"accountState"))
1640 if (ledger.
get().isMember(jss::ledger_index))
1642 seq = ledger.
get()[jss::ledger_index].asUInt();
1645 if (ledger.
get().isMember(
"close_time"))
1648 using d = tp::duration;
1649 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1651 if (ledger.
get().isMember(
"close_time_resolution"))
1654 closeTimeResolution =
seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1656 if (ledger.
get().isMember(
"close_time_estimated"))
1658 closeTimeEstimated = ledger.
get()[
"close_time_estimated"].asBool();
1660 if (ledger.
get().isMember(
"total_coins"))
1662 totalDrops = beast::lexicalCastThrow<std::uint64_t>(ledger.
get()[
"total_coins"].asString());
1665 ledger = ledger.
get()[
"accountState"];
1668 if (!ledger.
get().isArrayOrNull())
1670 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1675 loadLedger->setTotalDrops(totalDrops);
1677 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1683 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1691 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1701 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1709 if (!loadLedger->addSLE(sle))
1711 JLOG(m_journal.fatal()) <<
"Couldn't add serialized ledger: " << uIndex;
1719 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()),
1720 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1721 loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated);
1727 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1733ApplicationImp::loadOldLedger(
1745 if (!ledgerID.
empty())
1746 loadLedger = loadLedgerFromFile(ledgerID);
1748 else if (ledgerID.
length() == 64)
1752 if (
hash.parseHex(ledgerID))
1761 if (il->checkLocal())
1762 loadLedger = il->getLedger();
1766 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1768 loadLedger = getLastFullLedger();
1787 replayLedger = loadLedger;
1789 JLOG(m_journal.info()) <<
"Loading parent ledger";
1791 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1794 JLOG(m_journal.info()) <<
"Loading parent ledger from node store";
1799 replayLedger->header().parentHash,
1801 InboundLedger::Reason::GENERIC,
1805 if (il->checkLocal())
1806 loadLedger = il->getLedger();
1811 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1813 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1820 using namespace std::chrono_literals;
1821 using namespace date;
1824 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1826 JLOG(m_journal.fatal()) <<
"\n\n*** WARNING ***\n"
1827 "You are replaying a ledger from before "
1828 << to_string(ledgerWarnTimePoint)
1830 "This replay will not handle your ledger as it was "
1832 "handled.\nConsider running an earlier version of rippled "
1834 "get the older rules.\n*** CONTINUING ***\n";
1837 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash <<
" seq:" << loadLedger->header().seq;
1839 if (loadLedger->header().accountHash.isZero())
1842 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
1843 UNREACHABLE(
"xrpl::ApplicationImp::loadOldLedger : ledger is empty");
1848 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
1851 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
1853 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
1859 if (!loadLedger->assertSensible(journal(
"Ledger")))
1862 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
1864 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
1870 m_ledgerMaster->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq);
1872 m_ledgerMaster->switchLCL(loadLedger);
1873 loadLedger->setValidated();
1874 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
1875 openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
1883 for (
auto const& [_, tx] : replayData->orderedTxns())
1886 auto txID = tx->getTransactionID();
1887 if (trapTxID == txID)
1890 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
1896 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
1904 m_ledgerMaster->takeReplay(std::move(replayData));
1906 if (trapTxID && !trapTxID_)
1908 JLOG(m_journal.fatal()) <<
"Ledger " << replayLedger->header().seq
1909 <<
" does not contain the transaction hash " << *trapTxID;
1916 JLOG(m_journal.fatal()) <<
"While loading specified ledger: " << mn.
what();
1919 catch (boost::bad_lexical_cast&)
1921 JLOG(m_journal.fatal()) <<
"Ledger specified '" << ledgerID <<
"' is not valid";
1931 if (!config().ELB_SUPPORT)
1936 reason =
"Server is shutting down";
1940 if (getOPs().isNeedNetworkLedger())
1942 reason =
"Not synchronized with network yet";
1946 if (getOPs().isAmendmentBlocked())
1948 reason =
"Server version too old";
1952 if (getOPs().isUNLBlocked())
1954 reason =
"No valid validator list available";
1958 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
1960 reason =
"Not synchronized with network";
1964 if (!getLedgerMaster().isCaughtUp(reason))
1967 if (getFeeTrack().isLoadedLocal())
1969 reason =
"Too much load";
1979 return logs_->journal(name);
1983ApplicationImp::setMaxDisallowedLedger()
1985 auto seq = getRelationalDatabase().getMaxLedgerSeq();
1987 maxDisallowedLedger_ = *seq;
1989 JLOG(m_journal.trace()) <<
"Max persisted ledger is " << maxDisallowedLedger_;
2009 for (
auto const& [name, ep] : endpoints)
2011 if (!config.
exists(name))
2014 auto& section = config[name];
2015 auto const optPort = section.get(
"port");
2018 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::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
Application & app() 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(ServiceRegistry ®istry, 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)
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::pair< PublicKey, SecretKey > getNodeIdentity(soci::session &session)
Returns a stable public and private key for this node.
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< 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)
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()