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();
912 std::size_t const oldLedgerMasterCacheSize = getLedgerMaster().getFetchPackCacheSize();
914 getLedgerMaster().sweep();
916 JLOG(m_journal.debug()) <<
"LedgerMaster sweep. Size before: " << oldLedgerMasterCacheSize
917 <<
"; size after: " << getLedgerMaster().getFetchPackCacheSize();
921 std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
923 getTempNodeCache().sweep();
925 JLOG(m_journal.debug()) <<
"TempNodeCache sweep. Size before: " << oldTempNodeCacheSize
926 <<
"; size after: " << getTempNodeCache().size();
929 std::size_t const oldCurrentCacheSize = getValidations().sizeOfCurrentCache();
930 std::size_t const oldSizeSeqEnforcesSize = getValidations().sizeOfSeqEnforcersCache();
931 std::size_t const oldByLedgerSize = getValidations().sizeOfByLedgerCache();
932 std::size_t const oldBySequenceSize = getValidations().sizeOfBySequenceCache();
934 getValidations().expire(m_journal);
936 JLOG(m_journal.debug()) <<
"Validations Current expire. Size before: " << oldCurrentCacheSize
937 <<
"; size after: " << getValidations().sizeOfCurrentCache();
939 JLOG(m_journal.debug()) <<
"Validations SeqEnforcer expire. Size before: " << oldSizeSeqEnforcesSize
940 <<
"; size after: " << getValidations().sizeOfSeqEnforcersCache();
942 JLOG(m_journal.debug()) <<
"Validations ByLedger expire. Size before: " << oldByLedgerSize
943 <<
"; size after: " << getValidations().sizeOfByLedgerCache();
945 JLOG(m_journal.debug()) <<
"Validations BySequence expire. Size before: " << oldBySequenceSize
946 <<
"; size after: " << getValidations().sizeOfBySequenceCache();
949 std::size_t const oldInboundLedgersSize = getInboundLedgers().cacheSize();
951 getInboundLedgers().sweep();
953 JLOG(m_journal.debug()) <<
"InboundLedgers sweep. Size before: " << oldInboundLedgersSize
954 <<
"; size after: " << getInboundLedgers().cacheSize();
957 size_t const oldTasksSize = getLedgerReplayer().tasksSize();
958 size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
959 size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
961 getLedgerReplayer().sweep();
963 JLOG(m_journal.debug()) <<
"LedgerReplayer tasks sweep. Size before: " << oldTasksSize
964 <<
"; size after: " << getLedgerReplayer().tasksSize();
966 JLOG(m_journal.debug()) <<
"LedgerReplayer deltas sweep. Size before: " << oldDeltasSize
967 <<
"; size after: " << getLedgerReplayer().deltasSize();
969 JLOG(m_journal.debug()) <<
"LedgerReplayer skipLists sweep. Size before: " << oldSkipListsSize
970 <<
"; size after: " << getLedgerReplayer().skipListsSize();
973 std::size_t const oldAcceptedLedgerSize = m_acceptedLedgerCache.size();
975 m_acceptedLedgerCache.sweep();
977 JLOG(m_journal.debug()) <<
"AcceptedLedgerCache sweep. Size before: " << oldAcceptedLedgerSize
978 <<
"; size after: " << m_acceptedLedgerCache.size();
981 std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
985 JLOG(m_journal.debug()) <<
"CachedSLEs sweep. Size before: " << oldCachedSLEsSize
986 <<
"; size after: " << cachedSLEs_.size();
996 return maxDisallowedLedger_;
1011 startGenesisLedger();
1014 getLastFullLedger();
1023 setMaxDisallowedLedger();
1030ApplicationImp::setup(boost::program_options::variables_map
const& cmdline)
1040 m_signals.add(SIGINT);
1041 m_signals.add(SIGTERM);
1042 m_signals.async_wait([
this](boost::system::error_code
const& ec,
int signum) {
1044 if (ec == boost::asio::error::operation_aborted)
1047 JLOG(m_journal.info()) <<
"Received signal " << signum;
1049 if (signum == SIGTERM || signum == SIGINT)
1050 signalStop(
"Signal: " + to_string(signum));
1053 auto debug_log = config_->getDebugLogFile();
1055 if (!debug_log.empty())
1060 if (!logs_->open(debug_log))
1061 std::cerr <<
"Can't open log file " << debug_log <<
'\n';
1064 if (logs_->threshold() > kDebug)
1065 logs_->threshold(kDebug);
1068 JLOG(m_journal.info()) <<
"Process starting: " << BuildInfo::getFullVersionString()
1069 <<
", Instance Cookie: " << instanceCookie_;
1071 if (numberOfThreads(*config_) < 2)
1073 JLOG(m_journal.warn()) <<
"Limited to a single I/O service thread by "
1074 "system configuration.";
1078 logs_->silent(config_->silent());
1080 if (!initRelationalDatabase() || !initNodeStore())
1083 if (!peerReservations_->load(getWalletDB()))
1085 JLOG(m_journal.fatal()) <<
"Cannot find peer reservations!";
1089 if (validatorKeys_.keys)
1090 setMaxDisallowedLedger();
1094 auto const supported = []() {
1095 auto const& amendments = detail::supportedAmendments();
1097 supported.reserve(amendments.size());
1098 for (
auto const& [a, vote] : amendments)
1101 XRPL_ASSERT(f,
"xrpl::ApplicationImp::setup : registered feature");
1103 supported.emplace_back(a, *f, vote);
1107 Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
1109 Section const& upVoted = config_->section(SECTION_AMENDMENTS);
1112 *
this, config().AMENDMENT_MAJORITY_TIME, supported, upVoted, downVoted, logs_->journal(
"Amendments"));
1115 Pathfinder::initPathTable();
1117 auto const startUp = config_->START_UP;
1118 JLOG(m_journal.debug()) <<
"startUp: " << startUp;
1119 if (startUp == Config::FRESH)
1121 JLOG(m_journal.info()) <<
"Starting new Ledger";
1123 startGenesisLedger();
1125 else if (startUp == Config::LOAD || startUp == Config::LOAD_FILE || startUp == Config::REPLAY)
1127 JLOG(m_journal.info()) <<
"Loading specified Ledger";
1130 config_->START_LEDGER, startUp == Config::REPLAY, startUp == Config::LOAD_FILE, config_->TRAP_TX_HASH))
1132 JLOG(m_journal.error()) <<
"The specified ledger could not be loaded.";
1133 if (config_->FAST_LOAD)
1137 startGenesisLedger();
1145 else if (startUp == Config::NETWORK)
1149 if (!config_->standalone())
1150 m_networkOPs->setNeedNetworkLedger();
1152 startGenesisLedger();
1156 startGenesisLedger();
1159 if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
1161 m_ledgerMaster->setLedgerRangePresent(forcedRange->first, forcedRange->second);
1164 m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
1168 if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
1170 JLOG(m_journal.fatal()) <<
"Invalid entry in cluster configuration.";
1175 if (validatorKeys_.configInvalid())
1178 if (!validatorManifests_->load(
1180 "ValidatorManifests",
1181 validatorKeys_.manifest,
1182 config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
1184 JLOG(m_journal.fatal()) <<
"Invalid configured validator manifest.";
1188 publisherManifests_->load(getWalletDB(),
"PublisherManifests");
1197 if (validatorKeys_.keys)
1198 localSigningKey = validatorKeys_.keys->publicKey;
1201 if (!validators_->load(
1203 config().section(SECTION_VALIDATORS).values(),
1204 config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
1205 config().VALIDATOR_LIST_THRESHOLD))
1207 JLOG(m_journal.fatal()) <<
"Invalid entry in validator configuration.";
1212 if (!validatorSites_->load(config().section(SECTION_VALIDATOR_LIST_SITES).values()))
1214 JLOG(m_journal.fatal()) <<
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES <<
"]";
1219 m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
1240 m_collectorManager->collector());
1244 if (!m_networkOPs->beginConsensus(m_ledgerMaster->getClosedLedger()->header().hash, {}))
1246 JLOG(m_journal.fatal()) <<
"Unable to start consensus";
1255 serverHandler_->setup(setup, m_journal);
1260 if (
auto stream = m_journal.fatal())
1262 stream <<
"Unable to setup server handler";
1264 stream <<
": " << e.
what();
1271 if (!config_->standalone())
1275 if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
1277 JLOG(m_journal.warn()) <<
"No outbound peer connections will be made";
1282 m_networkOPs->setStateTimer();
1286 JLOG(m_journal.warn()) <<
"Running in standalone mode";
1288 m_networkOPs->setStandAlone();
1291 if (config_->canSign())
1293 JLOG(m_journal.warn()) <<
"*** The server is configured to allow the "
1294 "'sign' and 'sign_for'";
1295 JLOG(m_journal.warn()) <<
"*** commands. These commands have security "
1296 "implications and have";
1297 JLOG(m_journal.warn()) <<
"*** been deprecated. They will be removed "
1298 "in a future release of";
1299 JLOG(m_journal.warn()) <<
"*** rippled.";
1300 JLOG(m_journal.warn()) <<
"*** If you do not use them to sign "
1301 "transactions please edit your";
1302 JLOG(m_journal.warn()) <<
"*** configuration file and remove the [enable_signing] stanza.";
1303 JLOG(m_journal.warn()) <<
"*** If you do use them to sign transactions "
1304 "please migrate to a";
1305 JLOG(m_journal.warn()) <<
"*** standalone signing solution as soon as possible.";
1311 for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
1316 if (!jrReader.
parse(cmd, jvCommand))
1318 JLOG(m_journal.fatal()) <<
"Couldn't parse entry in [" << SECTION_RPC_STARTUP <<
"]: '" << cmd;
1321 if (!config_->quiet())
1323 JLOG(m_journal.fatal()) <<
"Startup RPC: " << jvCommand <<
std::endl;
1329 {journal(
"RPCHandler"),
1338 RPC::apiMaximumSupportedVersion},
1342 RPC::doCommand(context, jvResult);
1344 if (!config_->quiet())
1346 JLOG(m_journal.fatal()) <<
"Result: " << jvResult <<
std::endl;
1350 validatorSites_->start();
1356ApplicationImp::start(
bool withTimers)
1358 JLOG(m_journal.info()) <<
"Application starting. Version is " << BuildInfo::getVersionString();
1366 m_io_latency_sampler.start();
1367 m_resolver->start();
1368 m_loadManager->start();
1369 m_shaMapStore->start();
1373 if (grpcServer_->start())
1374 fixConfigPorts(*config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
1376 ledgerCleaner_->start();
1381ApplicationImp::run()
1383 if (!config_->standalone())
1389 getLoadManager().activateStallDetector();
1394 JLOG(m_journal.debug()) <<
"Application stopping";
1396 m_io_latency_sampler.cancel_async();
1404 m_io_latency_sampler.cancel();
1406 m_resolver->stop_async();
1416 sweepTimer_.cancel();
1418 catch (boost::system::system_error
const& e)
1420 JLOG(m_journal.error()) <<
"Application: sweepTimer cancel error: " << e.what();
1425 entropyTimer_.cancel();
1427 catch (boost::system::system_error
const& e)
1429 JLOG(m_journal.error()) <<
"Application: entropyTimer cancel error: " << e.what();
1435 using namespace std::chrono_literals;
1437 waitHandlerCounter_.join(
"Application", 1s, m_journal);
1439 mValidations.flush();
1441 validatorSites_->stop();
1444 validatorManifests_->save(
1445 getWalletDB(),
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
return validators().listed(pubKey); });
1447 publisherManifests_->save(getWalletDB(),
"PublisherManifests", [
this](
PublicKey const& pubKey) {
1448 return validators().trustedPublisher(pubKey);
1453 m_loadManager->stop();
1454 m_shaMapStore->stop();
1458 grpcServer_->stop();
1459 m_networkOPs->stop();
1460 serverHandler_->stop();
1461 m_ledgerReplayer->stop();
1462 m_inboundTransactions->stop();
1463 m_inboundLedgers->stop();
1464 ledgerCleaner_->stop();
1465 m_nodeStore->stop();
1468 JLOG(m_journal.info()) <<
"Done.";
1477 JLOG(m_journal.warn()) <<
"Server stopping";
1479 JLOG(m_journal.warn()) <<
"Server stopping: " << msg;
1481 isTimeToStop.notify_all();
1486ApplicationImp::checkSigs()
const
1492ApplicationImp::checkSigs(
bool check)
1498ApplicationImp::isStopping()
const
1504ApplicationImp::fdRequired()
const
1511 needed += 2 * overlay_->limit();
1515 needed +=
std::max(5, m_shaMapStore->fdRequired());
1519 for (
auto const& p : serverHandler_->setup().ports)
1529ApplicationImp::startGenesisLedger()
1532 (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired() :
std::vector<uint256>{};
1536 m_ledgerMaster->storeLedger(genesis);
1539 next->updateSkipList();
1541 next->header().seq < XRP_LEDGER_EARLIEST_FEES || next->read(keylet::fees()),
1542 "xrpl::ApplicationImp::startGenesisLedger : valid ledger fees");
1543 next->setImmutable();
1544 openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
1545 m_ledgerMaster->storeLedger(next);
1546 m_ledgerMaster->switchLCL(next);
1550ApplicationImp::getLastFullLedger()
1552 auto j = journal(
"Ledger");
1562 ledger->header().seq < XRP_LEDGER_EARLIEST_FEES || ledger->read(keylet::fees()),
1563 "xrpl::ApplicationImp::getLastFullLedger : valid ledger fees");
1564 ledger->setImmutable();
1566 if (getLedgerMaster().haveLedger(seq))
1567 ledger->setValidated();
1569 if (ledger->header().hash ==
hash)
1571 JLOG(j.trace()) <<
"Loaded ledger: " <<
hash;
1575 if (
auto stream = j.error())
1577 stream <<
"Failed on ledger";
1579 addJson(p, {*ledger,
nullptr, LedgerFill::full});
1587 JLOG(j.warn()) <<
"Ledger in database: " << mn.
what();
1601 JLOG(m_journal.fatal()) <<
"Unable to open file '" << name <<
"'";
1608 if (!reader.
parse(ledgerFile, jLedger))
1610 JLOG(m_journal.fatal()) <<
"Unable to parse ledger JSON";
1617 if (ledger.
get().isMember(
"result"))
1618 ledger = ledger.
get()[
"result"];
1620 if (ledger.
get().isMember(
"ledger"))
1621 ledger = ledger.
get()[
"ledger"];
1624 auto closeTime = timeKeeper().closeTime();
1625 using namespace std::chrono_literals;
1626 auto closeTimeResolution = 30s;
1627 bool closeTimeEstimated =
false;
1630 if (ledger.
get().isMember(
"accountState"))
1632 if (ledger.
get().isMember(jss::ledger_index))
1634 seq = ledger.
get()[jss::ledger_index].asUInt();
1637 if (ledger.
get().isMember(
"close_time"))
1640 using d = tp::duration;
1641 closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
1643 if (ledger.
get().isMember(
"close_time_resolution"))
1646 closeTimeResolution =
seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
1648 if (ledger.
get().isMember(
"close_time_estimated"))
1650 closeTimeEstimated = ledger.
get()[
"close_time_estimated"].asBool();
1652 if (ledger.
get().isMember(
"total_coins"))
1654 totalDrops = beast::lexicalCastThrow<std::uint64_t>(ledger.
get()[
"total_coins"].asString());
1657 ledger = ledger.
get()[
"accountState"];
1660 if (!ledger.
get().isArrayOrNull())
1662 JLOG(m_journal.fatal()) <<
"State nodes must be an array";
1667 loadLedger->setTotalDrops(totalDrops);
1669 for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
1675 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1683 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1693 JLOG(m_journal.fatal()) <<
"Invalid entry in ledger";
1701 if (!loadLedger->addSLE(sle))
1703 JLOG(m_journal.fatal()) <<
"Couldn't add serialized ledger: " << uIndex;
1711 loadLedger->header().seq < XRP_LEDGER_EARLIEST_FEES || loadLedger->read(keylet::fees()),
1712 "xrpl::ApplicationImp::loadLedgerFromFile : valid ledger fees");
1713 loadLedger->setAccepted(closeTime, closeTimeResolution, !closeTimeEstimated);
1719 JLOG(m_journal.fatal()) <<
"Ledger contains invalid data: " << x.
what();
1725ApplicationImp::loadOldLedger(
1737 if (!ledgerID.
empty())
1738 loadLedger = loadLedgerFromFile(ledgerID);
1740 else if (ledgerID.
length() == 64)
1744 if (
hash.parseHex(ledgerID))
1753 if (il->checkLocal())
1754 loadLedger = il->getLedger();
1758 else if (ledgerID.
empty() || boost::iequals(ledgerID,
"latest"))
1760 loadLedger = getLastFullLedger();
1779 replayLedger = loadLedger;
1781 JLOG(m_journal.info()) <<
"Loading parent ledger";
1783 loadLedger =
loadByHash(replayLedger->header().parentHash, *
this);
1786 JLOG(m_journal.info()) <<
"Loading parent ledger from node store";
1791 replayLedger->header().parentHash,
1793 InboundLedger::Reason::GENERIC,
1797 if (il->checkLocal())
1798 loadLedger = il->getLedger();
1803 JLOG(m_journal.fatal()) <<
"Replay ledger missing/damaged";
1805 "xrpl::ApplicationImp::loadOldLedger : replay ledger "
1812 using namespace std::chrono_literals;
1813 using namespace date;
1816 if (loadLedger->header().closeTime < ledgerWarnTimePoint)
1818 JLOG(m_journal.fatal()) <<
"\n\n*** WARNING ***\n"
1819 "You are replaying a ledger from before "
1820 << to_string(ledgerWarnTimePoint)
1822 "This replay will not handle your ledger as it was "
1824 "handled.\nConsider running an earlier version of rippled "
1826 "get the older rules.\n*** CONTINUING ***\n";
1829 JLOG(m_journal.info()) <<
"Loading ledger " << loadLedger->header().hash <<
" seq:" << loadLedger->header().seq;
1831 if (loadLedger->header().accountHash.isZero())
1834 JLOG(m_journal.fatal()) <<
"Ledger is empty.";
1835 UNREACHABLE(
"xrpl::ApplicationImp::loadOldLedger : ledger is empty");
1840 if (!loadLedger->walkLedger(journal(
"Ledger"),
true))
1843 JLOG(m_journal.fatal()) <<
"Ledger is missing nodes.";
1845 "xrpl::ApplicationImp::loadOldLedger : ledger is missing "
1851 if (!loadLedger->assertSensible(journal(
"Ledger")))
1854 JLOG(m_journal.fatal()) <<
"Ledger is not sensible.";
1856 "xrpl::ApplicationImp::loadOldLedger : ledger is not "
1862 m_ledgerMaster->setLedgerRangePresent(loadLedger->header().seq, loadLedger->header().seq);
1864 m_ledgerMaster->switchLCL(loadLedger);
1865 loadLedger->setValidated();
1866 m_ledgerMaster->setFullLedger(loadLedger,
true,
false);
1867 openLedger_.emplace(loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
1875 for (
auto const& [_, tx] : replayData->orderedTxns())
1878 auto txID = tx->getTransactionID();
1879 if (trapTxID == txID)
1882 JLOG(m_journal.debug()) <<
"Trap transaction set: " << txID;
1888 forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
1896 m_ledgerMaster->takeReplay(std::move(replayData));
1898 if (trapTxID && !trapTxID_)
1900 JLOG(m_journal.fatal()) <<
"Ledger " << replayLedger->header().seq
1901 <<
" does not contain the transaction hash " << *trapTxID;
1908 JLOG(m_journal.fatal()) <<
"While loading specified ledger: " << mn.
what();
1911 catch (boost::bad_lexical_cast&)
1913 JLOG(m_journal.fatal()) <<
"Ledger specified '" << ledgerID <<
"' is not valid";
1923 if (!config().ELB_SUPPORT)
1928 reason =
"Server is shutting down";
1932 if (getOPs().isNeedNetworkLedger())
1934 reason =
"Not synchronized with network yet";
1938 if (getOPs().isAmendmentBlocked())
1940 reason =
"Server version too old";
1944 if (getOPs().isUNLBlocked())
1946 reason =
"No valid validator list available";
1950 if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
1952 reason =
"Not synchronized with network";
1956 if (!getLedgerMaster().isCaughtUp(reason))
1959 if (getFeeTrack().isLoadedLocal())
1961 reason =
"Too much load";
1971 return logs_->journal(name);
1975ApplicationImp::setMaxDisallowedLedger()
1977 auto seq = getRelationalDatabase().getMaxLedgerSeq();
1979 maxDisallowedLedger_ = *seq;
1981 JLOG(m_journal.trace()) <<
"Max persisted ledger is " << maxDisallowedLedger_;
2001 for (
auto const& [name, ep] : endpoints)
2003 if (!config.
exists(name))
2006 auto& section = config[name];
2007 auto const optPort = section.get(
"port");
2010 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()