1#include <xrpld/app/consensus/RCLValidations.h>
2#include <xrpld/app/ledger/InboundLedgers.h>
3#include <xrpld/app/ledger/InboundTransactions.h>
4#include <xrpld/app/ledger/LedgerCleaner.h>
5#include <xrpld/app/ledger/LedgerMaster.h>
6#include <xrpld/app/ledger/LedgerReplayer.h>
7#include <xrpld/app/ledger/LedgerToJson.h>
8#include <xrpld/app/ledger/OpenLedger.h>
9#include <xrpld/app/ledger/OrderBookDB.h>
10#include <xrpld/app/ledger/PendingSaves.h>
11#include <xrpld/app/ledger/TransactionMaster.h>
12#include <xrpld/app/main/Application.h>
13#include <xrpld/app/main/BasicApp.h>
14#include <xrpld/app/main/DBInit.h>
15#include <xrpld/app/main/GRPCServer.h>
16#include <xrpld/app/main/LoadManager.h>
17#include <xrpld/app/main/NodeIdentity.h>
18#include <xrpld/app/main/NodeStoreScheduler.h>
19#include <xrpld/app/misc/AmendmentTable.h>
20#include <xrpld/app/misc/HashRouter.h>
21#include <xrpld/app/misc/LoadFeeTrack.h>
22#include <xrpld/app/misc/NetworkOPs.h>
23#include <xrpld/app/misc/SHAMapStore.h>
24#include <xrpld/app/misc/TxQ.h>
25#include <xrpld/app/misc/ValidatorKeys.h>
26#include <xrpld/app/misc/ValidatorSite.h>
27#include <xrpld/app/paths/PathRequests.h>
28#include <xrpld/app/rdb/RelationalDatabase.h>
29#include <xrpld/app/rdb/Wallet.h>
30#include <xrpld/app/tx/apply.h>
31#include <xrpld/core/DatabaseCon.h>
32#include <xrpld/overlay/Cluster.h>
33#include <xrpld/overlay/PeerReservationTable.h>
34#include <xrpld/overlay/PeerSet.h>
35#include <xrpld/overlay/make_Overlay.h>
36#include <xrpld/shamap/NodeFamily.h>
38#include <xrpl/basics/ByteUtilities.h>
39#include <xrpl/basics/ResolverAsio.h>
40#include <xrpl/basics/random.h>
41#include <xrpl/beast/asio/io_latency_probe.h>
42#include <xrpl/beast/core/LexicalCast.h>
43#include <xrpl/core/PerfLog.h>
44#include <xrpl/crypto/csprng.h>
45#include <xrpl/json/json_reader.h>
46#include <xrpl/nodestore/DummyScheduler.h>
47#include <xrpl/protocol/ApiVersion.h>
48#include <xrpl/protocol/BuildInfo.h>
49#include <xrpl/protocol/Feature.h>
50#include <xrpl/protocol/Protocol.h>
51#include <xrpl/protocol/STParsedJSON.h>
52#include <xrpl/resource/Fees.h>
54#include <boost/algorithm/string/predicate.hpp>
55#include <boost/asio/steady_timer.hpp>
56#include <boost/system/error_code.hpp>
91 boost::asio::io_context& ios)
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();
217#if XRPL_SINGLE_IO_SERVICE_THREAD
248 perf::setup_PerfLog(
config_->section(
"perf"),
config_->CONFIG_DIR),
280 logs_->journal(
"JobQueue"),
330 logs_->journal(
"TaggedCache"))
342 logs_->journal(
"NetworkOPs"),
357 config_->legacy(
"database_path"),
358 logs_->journal(
"ValidatorList"),
393 logs_->journal(
"Application"),
423 setup(boost::program_options::variables_map
const& cmdline)
override;
425 start(
bool withTimers)
override;
489 LogicError(
"Accessing Application::nodeIdentity() before it is initialized.");
512 "xrpl::ApplicationImp::getServerHandler : non-null server "
517 boost::asio::io_context&
719 XRPL_ASSERT(
overlay_,
"xrpl::ApplicationImp::overlay : non-null overlay");
726 XRPL_ASSERT(
txQ_,
"xrpl::ApplicationImp::getTxQ : non-null transaction queue");
735 "xrpl::ApplicationImp::getRelationalDatabase : non-null "
736 "relational database");
743 XRPL_ASSERT(
mWalletDB,
"xrpl::ApplicationImp::getWalletDB : non-null wallet database");
760 "xrpl::ApplicationImp::initRelationalDatabase : null wallet "
769 setup.useGlobalPragma =
false;
787 auto j =
logs_->journal(
"NodeObject");
796 JLOG(j.warn()) <<
"Starting node import from '" << source->getName() <<
"' to '" <<
m_nodeStore->getName()
800 auto const start = steady_clock::now();
804 auto const elapsed = duration_cast<seconds>(steady_clock::now() -
start);
805 JLOG(j.warn()) <<
"Node import from '" << source->getName() <<
"' took " << elapsed.count() <<
" seconds.";
827 if (
auto optionalCountedHandler =
waitHandlerCounter_.wrap([
this](boost::system::error_code
const& e) {
828 if (e.value() == boost::system::errc::success)
830 m_jobQueue->addJob(jtSWEEP,
"sweep", [this]() { doSweep(); });
833 if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted)
836 JLOG(m_journal.error()) <<
"Sweep timer got error '" << e.message() <<
"'. Restarting timer.";
844 sweepTimer_.async_wait(std::move(*optionalCountedHandler));
852 if (
auto optionalCountedHandler = waitHandlerCounter_.wrap([
this](boost::system::error_code
const& e) {
853 if (e.value() == boost::system::errc::success)
855 crypto_prng().mix_entropy();
859 if (e.value() != boost::system::errc::success && e.value() != boost::asio::error::operation_aborted)
862 JLOG(m_journal.error()) <<
"Entropy timer got error '" << e.message() <<
"'. Restarting timer.";
867 using namespace std::chrono_literals;
868 entropyTimer_.expires_after(5min);
869 entropyTimer_.async_wait(std::move(*optionalCountedHandler));
876 if (!config_->standalone() && !getRelationalDatabase().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();
913 getNodeStore().sweep();
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();
1034ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1044 m_signals.add(SIGINT);
1045 m_signals.add(SIGTERM);
1046 m_signals.async_wait([
this](boost::system::error_code
const& ec,
int signum) {
1048 if (ec == boost::asio::error::operation_aborted)
1051 JLOG(m_journal.info()) <<
"Received signal " << signum;
1053 if (signum == SIGTERM || signum == SIGINT)
1054 signalStop(
"Signal: " + to_string(signum));
1057 auto debug_log = config_->getDebugLogFile();
1059 if (!debug_log.empty())
1064 if (!logs_->open(debug_log))
1065 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1068 if (logs_->threshold() > kDebug)
1069 logs_->threshold(kDebug);
1072 JLOG(m_journal.info()) <<
"Process starting: " << BuildInfo::getFullVersionString()
1073 <<
", Instance Cookie: " << instanceCookie_;
1075 if (numberOfThreads(*config_) < 2)
1077 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1078 "system configuration.";
1082 logs_->silent(config_->silent());
1084 if (!initRelationalDatabase() || !initNodeStore())
1087 if (!peerReservations_->load(getWalletDB()))
1089 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1093 if (validatorKeys_.keys)
1094 setMaxDisallowedLedger();
1098 auto const supported = []() {
1099 auto const& amendments = detail::supportedAmendments();
1101 supported.reserve(amendments.size());
1102 for (
auto const& [a, vote] : amendments)
1105 XRPL_ASSERT(f,
"xrpl::ApplicationImp::setup : registered feature");
1107 supported.emplace_back(a, *f, vote);
1111 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1113 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1116 *
this, config().AMENDMENT_MAJORITY_TIME, supported, upVoted, downVoted, logs_->journal(
"Amendments"));
1119 Pathfinder::initPathTable();
1121 auto const startUp = config_->START_UP;
1122 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1123 if (startUp == Config::FRESH)
1125 JLOG(m_journal.info()) <<
"Starting new Ledger";
1127 startGenesisLedger();
1129 else if (startUp == Config::LOAD || startUp == Config::LOAD_FILE || startUp == Config::REPLAY)
1131 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1134 config_->START_LEDGER, startUp == Config::REPLAY, startUp == Config::LOAD_FILE, config_->TRAP_TX_HASH))
1136 JLOG(m_journal.error()) <<
"The specified ledger could not be loaded.";
1137 if (config_->FAST_LOAD)
1141 startGenesisLedger();
1149 else if (startUp == Config::NETWORK)
1153 if (!config_->standalone())
1154 m_networkOPs->setNeedNetworkLedger();
1156 startGenesisLedger();
1160 startGenesisLedger();
1163 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1165 m_ledgerMaster->setLedgerRangePresent(forcedRange->first, forcedRange->second);
1168 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1172 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1174 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1179 if (validatorKeys_.configInvalid())
1182 if (!validatorManifests_->load(
1184 "ValidatorManifests",
1185 validatorKeys_.manifest,
1186 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1188 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1192 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1201 if (validatorKeys_.keys)
1202 localSigningKey = validatorKeys_.keys->publicKey;
1205 if (!validators_->load(
1207 config().section(SECTION_VALIDATORS).values(),
1208 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1209 config().VALIDATOR_LIST_THRESHOLD))
1211 JLOG(m_journal.fatal()) <<
"Invalid entry in validator configuration.";
1216 if (!validatorSites_->load(config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1218 JLOG(m_journal.fatal()) <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1223 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1244 m_collectorManager->collector());
1248 if (!m_networkOPs->beginConsensus(m_ledgerMaster->getClosedLedger()->header().hash, {}))
1250 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1259 serverHandler_->setup(setup, m_journal);
1264 if (
auto stream = m_journal.fatal())
1266 stream <<
"Unable to setup server handler";
1268 stream <<
": " << e.
what();
1275 if (!config_->standalone())
1279 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1281 JLOG(m_journal.warn()) <<
"No outbound peer connections will be made";
1286 m_networkOPs->setStateTimer();
1290 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1292 m_networkOPs->setStandAlone();
1295 if (config_->canSign())
1297 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1298 "'sign' and 'sign_for'";
1299 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1300 "implications and have";
1301 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1302 "in a future release of";
1303 JLOG(m_journal.warn()) <<
"*** rippled.";
1304 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1305 "transactions please edit your";
1306 JLOG(m_journal.warn()) <<
"*** configuration file and remove the [enable_signing] stanza.";
1307 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1308 "please migrate to a";
1309 JLOG(m_journal.warn()) <<
"*** standalone signing solution as soon as possible.";
1315 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1320 if (!jrReader.
parse(cmd, jvCommand))
1322 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in [" << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1325 if (!config_->quiet())
1327 JLOG(m_journal.fatal()) <<
"Startup RPC: " << jvCommand <<
std::endl;
1333 {journal(
"RPCHandler"),
1342 RPC::apiMaximumSupportedVersion},
1346 RPC::doCommand(context, jvResult);
1348 if (!config_->quiet())
1350 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1354 validatorSites_->start();
1360ApplicationImp::start(
bool withTimers)
1362 JLOG(m_journal.info()) <<
"Application starting. Version is " << BuildInfo::getVersionString();
1370 m_io_latency_sampler.start();
1371 m_resolver->start();
1372 m_loadManager->start();
1373 m_shaMapStore->start();
1377 if (grpcServer_->start())
1378 fixConfigPorts(*config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1380 ledgerCleaner_->start();
1385ApplicationImp::run()
1387 if (!config_->standalone())
1393 getLoadManager().activateStallDetector();
1398 JLOG(m_journal.debug()) <<
"Application stopping";
1400 m_io_latency_sampler.cancel_async();
1408 m_io_latency_sampler.cancel();
1410 m_resolver->stop_async();
1420 sweepTimer_.cancel();
1422 catch (boost::system::system_error
const& e)
1424 JLOG(m_journal.error()) <<
"Application: sweepTimer cancel error: " << e.what();
1429 entropyTimer_.cancel();
1431 catch (boost::system::system_error
const& e)
1433 JLOG(m_journal.error()) <<
"Application: entropyTimer cancel error: " << e.what();
1439 using namespace std::chrono_literals;
1441 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1443 mValidations.flush();
1445 validatorSites_->stop();
1448 validatorManifests_->save(
1449 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
return validators().listed(pubKey); });
1451 publisherManifests_->save(getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1452 return validators().trustedPublisher(pubKey);
1457 m_loadManager->stop();
1458 m_shaMapStore->stop();
1462 grpcServer_->stop();
1463 m_networkOPs->stop();
1464 serverHandler_->stop();
1465 m_ledgerReplayer->stop();
1466 m_inboundTransactions->stop();
1467 m_inboundLedgers->stop();
1468 ledgerCleaner_->stop();
1469 m_nodeStore->stop();
1472 JLOG(m_journal.info()) <<
"Done.";
1481 JLOG(m_journal.warn()) <<
"Server stopping";
1483 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1485 isTimeToStop.notify_all();
1490ApplicationImp::checkSigs()
const
1496ApplicationImp::checkSigs(
bool check)
1502ApplicationImp::isStopping()
const
1508ApplicationImp::fdRequired()
const
1515 needed += 2 * overlay_->limit();
1519 needed +=
std::max(5, m_shaMapStore->fdRequired());
1523 for (
auto const& p : serverHandler_->setup().ports)
1533ApplicationImp::startGenesisLedger()
1536 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired() :
std::vector<uint256>{};
1540 m_ledgerMaster->storeLedger(genesis);
1543 next->updateSkipList();
1545 next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()),
1546 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1547 next->setImmutable();
1548 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1549 m_ledgerMaster->storeLedger(next);
1550 m_ledgerMaster->switchLCL(next);
1554ApplicationImp::getLastFullLedger()
1556 auto j = journal(
"Ledger");
1566 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
1567 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1568 ledger->setImmutable();
1570 if (getLedgerMaster().haveLedger(seq))
1571 ledger->setValidated();
1573 if (ledger->header().hash ==
hash)
1575 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1579 if (
auto stream = j.error())
1581 stream <<
"Failed on ledger";
1583 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1591 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1605 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1612 if (!reader.
parse(ledgerFile, jLedger))
1614 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1621 if (ledger.
get().isMember(
"result"))
1622 ledger = ledger.
get()[
"result"];
1624 if (ledger.
get().isMember(
"ledger"))
1625 ledger = ledger.
get()[
"ledger"];
1628 auto closeTime = timeKeeper().closeTime();
1629 using namespace std::chrono_literals;
1630 auto closeTimeResolution = 30s;
1631 bool closeTimeEstimated =
false;
1634 if (ledger.
get().isMember(
"accountState"))
1636 if (ledger.
get().isMember(jss::ledger_index))
1638 seq = ledger.
get()[jss::ledger_index].asUInt();
1641 if (ledger.
get().isMember(
"close_time"))
1644 using d = tp::duration;
1645 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1647 if (ledger.
get().isMember(
"close_time_resolution"))
1650 closeTimeResolution =
seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1652 if (ledger.
get().isMember(
"close_time_estimated"))
1654 closeTimeEstimated = ledger.
get()[
"close_time_estimated"].asBool();
1656 if (ledger.
get().isMember(
"total_coins"))
1658 totalDrops = beast::lexicalCastThrow<std::uint64_t>(ledger.
get()[
"total_coins"].asString());
1661 ledger = ledger.
get()[
"accountState"];
1664 if (!ledger.
get().isArrayOrNull())
1666 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1671 loadLedger->setTotalDrops(totalDrops);
1673 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1679 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1687 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1697 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1705 if (!loadLedger->addSLE(sle))
1707 JLOG(m_journal.fatal()) <<
"Couldn't add serialized ledger: " << uIndex;
1715 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()),
1716 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1717 loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated);
1723 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1729ApplicationImp::loadOldLedger(
1741 if (!ledgerID.
empty())
1742 loadLedger = loadLedgerFromFile(ledgerID);
1744 else if (ledgerID.
length() == 64)
1748 if (
hash.parseHex(ledgerID))
1757 if (il->checkLocal())
1758 loadLedger = il->getLedger();
1762 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1764 loadLedger = getLastFullLedger();
1783 replayLedger = loadLedger;
1785 JLOG(m_journal.info()) <<
"Loading parent ledger";
1787 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1790 JLOG(m_journal.info()) <<
"Loading parent ledger from node store";
1795 replayLedger->header().parentHash,
1797 InboundLedger::Reason::GENERIC,
1801 if (il->checkLocal())
1802 loadLedger = il->getLedger();
1807 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1809 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1816 using namespace std::chrono_literals;
1817 using namespace date;
1820 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1822 JLOG(m_journal.fatal()) <<
"\n\n*** WARNING ***\n"
1823 "You are replaying a ledger from before "
1824 << to_string(ledgerWarnTimePoint)
1826 "This replay will not handle your ledger as it was "
1828 "handled.\nConsider running an earlier version of rippled "
1830 "get the older rules.\n*** CONTINUING ***\n";
1833 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash <<
" seq:" << loadLedger->header().seq;
1835 if (loadLedger->header().accountHash.isZero())
1838 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
1839 UNREACHABLE(
"xrpl::ApplicationImp::loadOldLedger : ledger is empty");
1844 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
1847 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
1849 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
1855 if (!loadLedger->assertSensible(journal(
"Ledger")))
1858 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
1860 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
1866 m_ledgerMaster->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq);
1868 m_ledgerMaster->switchLCL(loadLedger);
1869 loadLedger->setValidated();
1870 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
1871 openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
1879 for (
auto const& [_, tx] : replayData->orderedTxns())
1882 auto txID = tx->getTransactionID();
1883 if (trapTxID == txID)
1886 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
1892 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
1900 m_ledgerMaster->takeReplay(std::move(replayData));
1902 if (trapTxID && !trapTxID_)
1904 JLOG(m_journal.fatal()) <<
"Ledger " << replayLedger->header().seq
1905 <<
" does not contain the transaction hash " << *trapTxID;
1912 JLOG(m_journal.fatal()) <<
"While loading specified ledger: " << mn.
what();
1915 catch (boost::bad_lexical_cast&)
1917 JLOG(m_journal.fatal()) <<
"Ledger specified '" << ledgerID <<
"' is not valid";
1927 if (!config().ELB_SUPPORT)
1932 reason =
"Server is shutting down";
1936 if (getOPs().isNeedNetworkLedger())
1938 reason =
"Not synchronized with network yet";
1942 if (getOPs().isAmendmentBlocked())
1944 reason =
"Server version too old";
1948 if (getOPs().isUNLBlocked())
1950 reason =
"No valid validator list available";
1954 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
1956 reason =
"Not synchronized with network";
1960 if (!getLedgerMaster().isCaughtUp(reason))
1963 if (getFeeTrack().isLoadedLocal())
1965 reason =
"Too much load";
1975 return logs_->journal(name);
1979ApplicationImp::setMaxDisallowedLedger()
1981 auto seq = getRelationalDatabase().getMaxLedgerSeq();
1983 maxDisallowedLedger_ = *seq;
1985 JLOG(m_journal.trace()) <<
"Max persisted ledger is " << maxDisallowedLedger_;
2005 for (
auto const& [name, ep] : endpoints)
2007 if (!config.
exists(name))
2010 auto& section = config[name];
2011 auto const optPort = section.get(
"port");
2014 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
OrderBookDB m_orderBookDB
ValidatorList & validators() override
PeerReservationTable & peerReservations() override
ApplicationImp(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
std::unique_ptr< PeerReservationTable > peerReservations_
std::unique_ptr< Resource::Manager > m_resourceManager
std::pair< PublicKey, SecretKey > const & nodeIdentity() override
std::unique_ptr< Logs > logs_
std::unique_ptr< DatabaseCon > mWalletDB
CachedSLEs & cachedSLEs() override
ValidatorSite & validatorSites() override
virtual std::optional< uint256 > const & trapTxID() const override
std::atomic_flag isTimeToStop
std::unique_ptr< LedgerMaster > m_ledgerMaster
std::unique_ptr< GRPCServer > grpcServer_
std::unique_ptr< ServerHandler > serverHandler_
ValidatorKeys const validatorKeys_
std::uint64_t instanceID() const override
Returns a 64-bit instance identifier, generated at startup.
OrderBookDB & getOrderBookDB() override
Family & getNodeFamily() override
void gotTXSet(std::shared_ptr< SHAMap > const &set, bool fromAcquire)
Config & config() override
DatabaseCon & getWalletDB() override
Retrieve the "wallet database".
PathRequests & getPathRequests() override
bool isStopping() const override
std::unique_ptr< TimeKeeper > timeKeeper_
beast::Journal journal(std::string const &name) override
std::unique_ptr< ValidatorSite > validatorSites_
RCLValidations mValidations
void signalStop(std::string msg) override
std::uint64_t const instanceCookie_
LedgerCleaner & getLedgerCleaner() override
ManifestCache & validatorManifests() override
AmendmentTable & getAmendmentTable() override
int fdRequired() const override
TaggedCache< uint256, AcceptedLedger > m_acceptedLedgerCache
std::unique_ptr< PathRequests > m_pathRequests
std::unique_ptr< JobQueue > m_jobQueue
LedgerMaster & getLedgerMaster() override
NodeStore::Database & getNodeStore() override
TransactionMaster m_txMaster
std::unique_ptr< Cluster > cluster_
std::unique_ptr< NetworkOPs > m_networkOPs
virtual ServerHandler & getServerHandler() override
JobQueue & getJobQueue() override
PendingSaves & pendingSaves() override
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
std::unique_ptr< InboundLedgers > m_inboundLedgers
TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache() override
perf::PerfLog & getPerfLog() override
boost::asio::signal_set m_signals
std::unique_ptr< LedgerReplayer > m_ledgerReplayer
bool exists(std::string const &name) const
Returns true if a section with the given name exists.
The role of a ClosureCounter is to assist in shutdown by letting callers wait for the completion of c...
Provides the beast::insight::Collector service.
Routing table for objects identified by hash.
Manages the lifetime of inbound ledgers.
Manages the acquisition and lifetime of transaction sets.
A pool of threads to perform work.
Check the ledger/transaction databases to make sure they have continuity.
Manages the lifetime of ledger replay tasks.
Manages the current fee schedule.
Manages partitions for logging.
Remembers manifests with the highest sequence number.
Provides server functionality for clients.
A NodeStore::Scheduler which uses the JobQueue.
Persistency layer for NodeObject.
Simple NodeStore Scheduler that just performs the tasks synchronously.
static Manager & instance()
Returns the instance of the manager singleton.
virtual std::unique_ptr< Database > make_Database(std::size_t burstSize, Scheduler &scheduler, int readThreads, Section const &backendParameters, beast::Journal journal)=0
Construct a NodeStore database.
Represents the open ledger.
Writable ledger view that accumulates state and tx changes.
void rawTxInsert(key_type const &key, std::shared_ptr< Serializer const > const &txn, std::shared_ptr< Serializer const > const &metaData) override
Add a transaction to the tx map.
Manages the set of connected peers.
Keeps track of which ledgers haven't been fully saved.
static std::unique_ptr< RelationalDatabase > init(Application &app, Config const &config, JobQueue &jobQueue)
init Creates and returns an appropriate RelationalDatabase instance based on configuration.
static std::unique_ptr< ResolverAsio > New(boost::asio::io_context &, beast::Journal)
An endpoint that consumes resources.
Tracks load and resource consumption.
class to create database, launch online delete thread, and related SQLite database
Holds the serialized result of parsing an input JSON object.
std::optional< STObject > object
The STObject if the parse was successful.
Holds a collection of configuration values.
std::size_t size() const
Returns the number of items in the container.
Manages various times used by the server.
Validator keys and manifest as set in configuration file.
std::optional< Keys > keys
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Singleton class that maintains performance counters and optionally writes Json-formatted data to a di...
T hardware_concurrency(T... args)
A namespace for easy access to logging severity values.
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
std::unique_ptr< Manager > make_Manager(beast::insight::Collector::ptr const &collector, beast::Journal journal)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
std::pair< PublicKey, SecretKey > getNodeIdentity(Application &app, boost::program_options::variables_map const &cmdline)
The cryptographic credentials identifying this server instance.
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
std::unique_ptr< LedgerCleaner > make_LedgerCleaner(Application &app, beast::Journal journal)
std::unique_ptr< LoadManager > make_LoadManager(Application &app, beast::Journal journal)
Stopwatch & stopwatch()
Returns an instance of a wall clock.
TxQ::Setup setup_TxQ(Config const &config)
Build a TxQ::Setup object from application configuration.
std::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
create_genesis_t const create_genesis
std::unique_ptr< NetworkOPs > make_NetworkOPs(Application &app, NetworkOPs::clock_type &clock, bool standalone, std::size_t minPeerCount, bool startvalid, JobQueue &job_queue, LedgerMaster &ledgerMaster, ValidatorKeys const &validatorKeys, boost::asio::io_context &io_svc, beast::Journal journal, beast::insight::Collector::ptr const &collector)
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
std::unique_ptr< SHAMapStore > make_SHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
std::unique_ptr< AmendmentTable > make_AmendmentTable(Application &app, std::chrono::seconds majorityTime, std::vector< AmendmentTable::FeatureInfo > const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
std::unique_ptr< CollectorManager > make_CollectorManager(Section const ¶ms, beast::Journal journal)
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
std::unique_ptr< InboundLedgers > make_InboundLedgers(Application &app, InboundLedgers::clock_type &clock, beast::insight::Collector::ptr const &collector)
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_context &io_context, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
constexpr auto megabytes(T value) noexcept
static void fixConfigPorts(Config &config, Endpoints const &endpoints)
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
void addJson(Json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a Json::Value with a description of the ledger.
Overlay::Setup setup_Overlay(BasicConfig const &config)
HashRouter::Setup setup_HashRouter(Config const &config)
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
std::unordered_map< std::string, boost::asio::ip::tcp::endpoint > Endpoints
std::optional< uint256 > getRegisteredFeature(std::string const &name)
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
std::unique_ptr< Overlay > make_Overlay(Application &app, Overlay::Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_context &io_context, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
Creates the implementation of Overlay.
static std::string importNodeDatabase()