20#include <xrpld/app/consensus/RCLValidations.h> 
   21#include <xrpld/app/ledger/InboundLedgers.h> 
   22#include <xrpld/app/ledger/InboundTransactions.h> 
   23#include <xrpld/app/ledger/LedgerCleaner.h> 
   24#include <xrpld/app/ledger/LedgerMaster.h> 
   25#include <xrpld/app/ledger/LedgerReplayer.h> 
   26#include <xrpld/app/ledger/LedgerToJson.h> 
   27#include <xrpld/app/ledger/OpenLedger.h> 
   28#include <xrpld/app/ledger/OrderBookDB.h> 
   29#include <xrpld/app/ledger/PendingSaves.h> 
   30#include <xrpld/app/ledger/TransactionMaster.h> 
   31#include <xrpld/app/main/Application.h> 
   32#include <xrpld/app/main/BasicApp.h> 
   33#include <xrpld/app/main/DBInit.h> 
   34#include <xrpld/app/main/GRPCServer.h> 
   35#include <xrpld/app/main/LoadManager.h> 
   36#include <xrpld/app/main/NodeIdentity.h> 
   37#include <xrpld/app/main/NodeStoreScheduler.h> 
   38#include <xrpld/app/misc/AmendmentTable.h> 
   39#include <xrpld/app/misc/HashRouter.h> 
   40#include <xrpld/app/misc/LoadFeeTrack.h> 
   41#include <xrpld/app/misc/NetworkOPs.h> 
   42#include <xrpld/app/misc/SHAMapStore.h> 
   43#include <xrpld/app/misc/TxQ.h> 
   44#include <xrpld/app/misc/ValidatorKeys.h> 
   45#include <xrpld/app/misc/ValidatorSite.h> 
   46#include <xrpld/app/paths/PathRequests.h> 
   47#include <xrpld/app/rdb/RelationalDatabase.h> 
   48#include <xrpld/app/rdb/Wallet.h> 
   49#include <xrpld/app/tx/apply.h> 
   50#include <xrpld/core/DatabaseCon.h> 
   51#include <xrpld/overlay/Cluster.h> 
   52#include <xrpld/overlay/PeerReservationTable.h> 
   53#include <xrpld/overlay/PeerSet.h> 
   54#include <xrpld/overlay/make_Overlay.h> 
   55#include <xrpld/perflog/PerfLog.h> 
   56#include <xrpld/shamap/NodeFamily.h> 
   58#include <xrpl/basics/ByteUtilities.h> 
   59#include <xrpl/basics/ResolverAsio.h> 
   60#include <xrpl/basics/random.h> 
   61#include <xrpl/beast/asio/io_latency_probe.h> 
   62#include <xrpl/beast/core/LexicalCast.h> 
   63#include <xrpl/crypto/csprng.h> 
   64#include <xrpl/json/json_reader.h> 
   65#include <xrpl/nodestore/DummyScheduler.h> 
   66#include <xrpl/protocol/ApiVersion.h> 
   67#include <xrpl/protocol/BuildInfo.h> 
   68#include <xrpl/protocol/Feature.h> 
   69#include <xrpl/protocol/Protocol.h> 
   70#include <xrpl/protocol/STParsedJSON.h> 
   71#include <xrpl/resource/Fees.h> 
   73#include <boost/algorithm/string/predicate.hpp> 
   74#include <boost/asio/steady_timer.hpp> 
   75#include <boost/system/error_code.hpp> 
  110            boost::asio::io_context& ios)
 
 
  124        template <
class Duration>
 
  129            auto const lastSample = ceil<milliseconds>(elapsed);
 
  133            if (lastSample >= 10ms)
 
  135            if (lastSample >= 500ms)
 
  138                    << 
"io_context latency = " << lastSample.count();
 
 
 
  244#if RIPPLE_SINGLE_IO_SERVICE_THREAD 
 
  292              config_->section(SECTION_INSIGHT),
 
  293              logs_->journal(
"Collector")))
 
  319              logs_->journal(
"JobQueue"),
 
  328              logs_->journal(
"SHAMapStore")))
 
  335              logs_->journal(
"TaggedCache"))
 
  342              logs_->journal(
"CachedSLEs"))
 
  348              logs_->journal(
"Resource")))
 
  396              logs_->journal(
"TaggedCache"))
 
  408              logs_->journal(
"NetworkOPs"),
 
  414              logs_->journal(
"PeerReservationTable")))
 
  426              config_->legacy(
"database_path"),
 
  427              logs_->journal(
"ValidatorList"),
 
  451              logs_->journal(
"Validations"))
 
  471              logs_->journal(
"Application"),
 
 
  501    setup(boost::program_options::variables_map 
const& cmdline) 
override;
 
  503    start(
bool withTimers) 
override;
 
  568            "Accessing Application::nodeIdentity() before it is initialized.");
 
 
  591            "ripple::ApplicationImp::getServerHandler : non-null server " 
 
  596    boost::asio::io_context&
 
  799            overlay_, 
"ripple::ApplicationImp::overlay : non-null overlay");
 
 
  808            "ripple::ApplicationImp::getTxQ : non-null transaction queue");
 
 
  817            "ripple::ApplicationImp::getRelationalDatabase : non-null " 
  818            "relational database");
 
 
  827            "ripple::ApplicationImp::getWalletDB : non-null wallet database");
 
 
  844            "ripple::ApplicationImp::initRelationalDatabase : null wallet " 
  854            setup.useGlobalPragma = 
false;
 
  861                << 
"Failed to initialize SQL databases: " << e.
what();
 
 
  873            auto j = 
logs_->journal(
"NodeObject");
 
  884            JLOG(j.warn()) << 
"Starting node import from '" << source->getName()
 
  888            auto const start = steady_clock::now();
 
  893                duration_cast<seconds>(steady_clock::now() - 
start);
 
  894            JLOG(j.warn()) << 
"Node import from '" << source->getName()
 
  895                           << 
"' took " << elapsed.count() << 
" seconds.";
 
 
  918                [
this](boost::system::error_code 
const& e) {
 
  919                    if (e.value() == boost::system::errc::success)
 
  922                            jtSWEEP, 
"sweep", [this]() { doSweep(); });
 
  925                    if (e.value() != boost::system::errc::success &&
 
  926                        e.value() != boost::asio::error::operation_aborted)
 
  929                        JLOG(m_journal.error())
 
  930                            << 
"Sweep timer got error '" << e.message()
 
  931                            << 
"'.  Restarting timer.";
 
  939            sweepTimer_.async_wait(std::move(*optionalCountedHandler));
 
 
  947        if (
auto optionalCountedHandler = waitHandlerCounter_.wrap(
 
  948                [
this](boost::system::error_code 
const& e) {
 
  949                    if (e.value() == boost::system::errc::success)
 
  951                        crypto_prng().mix_entropy();
 
  955                    if (e.value() != boost::system::errc::success &&
 
  956                        e.value() != boost::asio::error::operation_aborted)
 
  959                        JLOG(m_journal.error())
 
  960                            << 
"Entropy timer got error '" << e.message()
 
  961                            << 
"'.  Restarting timer.";
 
  966            using namespace std::chrono_literals;
 
  967            entropyTimer_.expires_after(5min);
 
  968            entropyTimer_.async_wait(std::move(*optionalCountedHandler));
 
 
  975        if (!config_->standalone() &&
 
  976            !getRelationalDatabase().transactionDbHasSpace(*config_))
 
  978            signalStop(
"Out of transaction DB space");
 
  987                nodeFamily_.getFullBelowCache();
 
  990                nodeFamily_.getTreeNodeCache();
 
  992            std::size_t const oldFullBelowSize = fullBelowCache->size();
 
  993            std::size_t const oldTreeNodeSize = treeNodeCache->size();
 
  997            JLOG(m_journal.debug())
 
  998                << 
"NodeFamily::FullBelowCache sweep.  Size before: " 
 1000                << 
"; size after: " << fullBelowCache->size();
 
 1002            JLOG(m_journal.debug())
 
 1003                << 
"NodeFamily::TreeNodeCache sweep.  Size before: " 
 1004                << oldTreeNodeSize << 
"; size after: " << treeNodeCache->size();
 
 1008                getMasterTransaction().getCache();
 
 1012            getMasterTransaction().sweep();
 
 1014            JLOG(m_journal.debug())
 
 1015                << 
"MasterTransaction sweep.  Size before: " << oldMasterTxSize
 
 1016                << 
"; size after: " << masterTxCache.
size();
 
 1020            getNodeStore().sweep();
 
 1024                getLedgerMaster().getFetchPackCacheSize();
 
 1026            getLedgerMaster().sweep();
 
 1028            JLOG(m_journal.debug())
 
 1029                << 
"LedgerMaster sweep.  Size before: " 
 1030                << oldLedgerMasterCacheSize << 
"; size after: " 
 1031                << getLedgerMaster().getFetchPackCacheSize();
 
 1035            std::size_t const oldTempNodeCacheSize = getTempNodeCache().size();
 
 1037            getTempNodeCache().sweep();
 
 1039            JLOG(m_journal.debug())
 
 1040                << 
"TempNodeCache sweep.  Size before: " << oldTempNodeCacheSize
 
 1041                << 
"; size after: " << getTempNodeCache().size();
 
 1045                getValidations().sizeOfCurrentCache();
 
 1047                getValidations().sizeOfSeqEnforcersCache();
 
 1049                getValidations().sizeOfByLedgerCache();
 
 1051                getValidations().sizeOfBySequenceCache();
 
 1053            getValidations().expire(m_journal);
 
 1055            JLOG(m_journal.debug())
 
 1056                << 
"Validations Current expire.  Size before: " 
 1057                << oldCurrentCacheSize
 
 1058                << 
"; size after: " << getValidations().sizeOfCurrentCache();
 
 1060            JLOG(m_journal.debug())
 
 1061                << 
"Validations SeqEnforcer expire.  Size before: " 
 1062                << oldSizeSeqEnforcesSize << 
"; size after: " 
 1063                << getValidations().sizeOfSeqEnforcersCache();
 
 1065            JLOG(m_journal.debug())
 
 1066                << 
"Validations ByLedger expire.  Size before: " 
 1068                << 
"; size after: " << getValidations().sizeOfByLedgerCache();
 
 1070            JLOG(m_journal.debug())
 
 1071                << 
"Validations BySequence expire.  Size before: " 
 1072                << oldBySequenceSize
 
 1073                << 
"; size after: " << getValidations().sizeOfBySequenceCache();
 
 1077                getInboundLedgers().cacheSize();
 
 1079            getInboundLedgers().sweep();
 
 1081            JLOG(m_journal.debug())
 
 1082                << 
"InboundLedgers sweep.  Size before: " 
 1083                << oldInboundLedgersSize
 
 1084                << 
"; size after: " << getInboundLedgers().cacheSize();
 
 1087            size_t const oldTasksSize = getLedgerReplayer().tasksSize();
 
 1088            size_t const oldDeltasSize = getLedgerReplayer().deltasSize();
 
 1089            size_t const oldSkipListsSize = getLedgerReplayer().skipListsSize();
 
 1091            getLedgerReplayer().sweep();
 
 1093            JLOG(m_journal.debug())
 
 1094                << 
"LedgerReplayer tasks sweep.  Size before: " << oldTasksSize
 
 1095                << 
"; size after: " << getLedgerReplayer().tasksSize();
 
 1097            JLOG(m_journal.debug())
 
 1098                << 
"LedgerReplayer deltas sweep.  Size before: " 
 1100                << 
"; size after: " << getLedgerReplayer().deltasSize();
 
 1102            JLOG(m_journal.debug())
 
 1103                << 
"LedgerReplayer skipLists sweep.  Size before: " 
 1105                << 
"; size after: " << getLedgerReplayer().skipListsSize();
 
 1109                m_acceptedLedgerCache.size();
 
 1111            m_acceptedLedgerCache.sweep();
 
 1113            JLOG(m_journal.debug())
 
 1114                << 
"AcceptedLedgerCache sweep.  Size before: " 
 1115                << oldAcceptedLedgerSize
 
 1116                << 
"; size after: " << m_acceptedLedgerCache.size();
 
 1119            std::size_t const oldCachedSLEsSize = cachedSLEs_.size();
 
 1121            cachedSLEs_.sweep();
 
 1123            JLOG(m_journal.debug())
 
 1124                << 
"CachedSLEs sweep.  Size before: " << oldCachedSLEsSize
 
 1125                << 
"; size after: " << cachedSLEs_.size();
 
 
 1135        return maxDisallowedLedger_;
 
 
 1150    startGenesisLedger();
 
 1153    getLastFullLedger();
 
 1166    setMaxDisallowedLedger();
 
 
 1173ApplicationImp::setup(boost::program_options::variables_map 
const& cmdline)
 
 1183    m_signals.add(SIGINT);
 
 1184    m_signals.add(SIGTERM);
 
 1185    m_signals.async_wait(
 
 1186        [
this](boost::system::error_code 
const& ec, 
int signum) {
 
 1188            if (ec == boost::asio::error::operation_aborted)
 
 1191            JLOG(m_journal.info()) << 
"Received signal " << signum;
 
 1193            if (signum == SIGTERM || signum == SIGINT)
 
 1194                signalStop(
"Signal: " + to_string(signum));
 
 1197    auto debug_log = config_->getDebugLogFile();
 
 1199    if (!debug_log.empty())
 
 1204        if (!logs_->open(debug_log))
 
 1205            std::cerr << 
"Can't open log file " << debug_log << 
'\n';
 
 1208        if (logs_->threshold() > kDebug)
 
 1209            logs_->threshold(kDebug);
 
 1212    JLOG(m_journal.info()) << 
"Process starting: " 
 1213                           << BuildInfo::getFullVersionString()
 
 1214                           << 
", Instance Cookie: " << instanceCookie_;
 
 1216    if (numberOfThreads(*config_) < 2)
 
 1218        JLOG(m_journal.warn()) << 
"Limited to a single I/O service thread by " 
 1219                                  "system configuration.";
 
 1223    logs_->silent(config_->silent());
 
 1225    if (!initRelationalDatabase() || !initNodeStore())
 
 1228    if (!peerReservations_->load(getWalletDB()))
 
 1230        JLOG(m_journal.fatal()) << 
"Cannot find peer reservations!";
 
 1234    if (validatorKeys_.keys)
 
 1235        setMaxDisallowedLedger();
 
 1239        auto const supported = []() {
 
 1240            auto const& amendments = detail::supportedAmendments();
 
 1242            supported.reserve(amendments.size());
 
 1243            for (
auto const& [a, vote] : amendments)
 
 1247                    f, 
"ripple::ApplicationImp::setup : registered feature");
 
 1249                    supported.emplace_back(a, *f, vote);
 
 1253        Section const& downVoted = config_->section(SECTION_VETO_AMENDMENTS);
 
 1255        Section const& upVoted = config_->section(SECTION_AMENDMENTS);
 
 1259            config().AMENDMENT_MAJORITY_TIME,
 
 1263            logs_->journal(
"Amendments"));
 
 1266    Pathfinder::initPathTable();
 
 1268    auto const startUp = config_->START_UP;
 
 1269    JLOG(m_journal.debug()) << 
"startUp: " << startUp;
 
 1270    if (startUp == Config::FRESH)
 
 1272        JLOG(m_journal.info()) << 
"Starting new Ledger";
 
 1274        startGenesisLedger();
 
 1277        startUp == Config::LOAD || startUp == Config::LOAD_FILE ||
 
 1278        startUp == Config::REPLAY)
 
 1280        JLOG(m_journal.info()) << 
"Loading specified Ledger";
 
 1283                config_->START_LEDGER,
 
 1284                startUp == Config::REPLAY,
 
 1285                startUp == Config::LOAD_FILE,
 
 1286                config_->TRAP_TX_HASH))
 
 1288            JLOG(m_journal.error())
 
 1289                << 
"The specified ledger could not be loaded.";
 
 1290            if (config_->FAST_LOAD)
 
 1294                startGenesisLedger();
 
 1302    else if (startUp == Config::NETWORK)
 
 1306        if (!config_->standalone())
 
 1307            m_networkOPs->setNeedNetworkLedger();
 
 1309        startGenesisLedger();
 
 1313        startGenesisLedger();
 
 1316    if (
auto const& forcedRange = config().FORCED_LEDGER_RANGE_PRESENT)
 
 1318        m_ledgerMaster->setLedgerRangePresent(
 
 1319            forcedRange->first, forcedRange->second);
 
 1322    m_orderBookDB.setup(getLedgerMaster().getCurrentLedger());
 
 1326    if (!cluster_->load(config().section(SECTION_CLUSTER_NODES)))
 
 1328        JLOG(m_journal.fatal()) << 
"Invalid entry in cluster configuration.";
 
 1333        if (validatorKeys_.configInvalid())
 
 1336        if (!validatorManifests_->load(
 
 1338                "ValidatorManifests",
 
 1339                validatorKeys_.manifest,
 
 1340                config().section(SECTION_VALIDATOR_KEY_REVOCATION).values()))
 
 1342            JLOG(m_journal.fatal()) << 
"Invalid configured validator manifest.";
 
 1346        publisherManifests_->load(getWalletDB(), 
"PublisherManifests");
 
 1355        if (validatorKeys_.keys)
 
 1356            localSigningKey = validatorKeys_.keys->publicKey;
 
 1359        if (!validators_->load(
 
 1361                config().section(SECTION_VALIDATORS).values(),
 
 1362                config().section(SECTION_VALIDATOR_LIST_KEYS).values(),
 
 1363                config().VALIDATOR_LIST_THRESHOLD))
 
 1365            JLOG(m_journal.fatal())
 
 1366                << 
"Invalid entry in validator configuration.";
 
 1371    if (!validatorSites_->load(
 
 1372            config().section(SECTION_VALIDATOR_LIST_SITES).values()))
 
 1374        JLOG(m_journal.fatal())
 
 1375            << 
"Invalid entry in [" << SECTION_VALIDATOR_LIST_SITES << 
"]";
 
 1380    m_amendmentTable->trustChanged(validators_->getQuorumKeys().second);
 
 1401        m_collectorManager->collector());
 
 1405    if (!m_networkOPs->beginConsensus(
 
 1406            m_ledgerMaster->getClosedLedger()->info().hash, {}))
 
 1408        JLOG(m_journal.fatal()) << 
"Unable to start consensus";
 
 1418            serverHandler_->setup(setup, m_journal);
 
 1423            if (
auto stream = m_journal.fatal())
 
 1425                stream << 
"Unable to setup server handler";
 
 1427                    stream << 
": " << e.
what();
 
 1434    if (!config_->standalone())
 
 1438        if (config_->PEER_PRIVATE && config_->IPS_FIXED.empty())
 
 1440            JLOG(m_journal.warn())
 
 1441                << 
"No outbound peer connections will be made";
 
 1446        m_networkOPs->setStateTimer();
 
 1450        JLOG(m_journal.warn()) << 
"Running in standalone mode";
 
 1452        m_networkOPs->setStandAlone();
 
 1455    if (config_->canSign())
 
 1457        JLOG(m_journal.warn()) << 
"*** The server is configured to allow the " 
 1458                                  "'sign' and 'sign_for'";
 
 1459        JLOG(m_journal.warn()) << 
"*** commands. These commands have security " 
 1460                                  "implications and have";
 
 1461        JLOG(m_journal.warn()) << 
"*** been deprecated. They will be removed " 
 1462                                  "in a future release of";
 
 1463        JLOG(m_journal.warn()) << 
"*** rippled.";
 
 1464        JLOG(m_journal.warn()) << 
"*** If you do not use them to sign " 
 1465                                  "transactions please edit your";
 
 1466        JLOG(m_journal.warn())
 
 1467            << 
"*** configuration file and remove the [enable_signing] stanza.";
 
 1468        JLOG(m_journal.warn()) << 
"*** If you do use them to sign transactions " 
 1469                                  "please migrate to a";
 
 1470        JLOG(m_journal.warn())
 
 1471            << 
"*** standalone signing solution as soon as possible.";
 
 1477    for (
auto cmd : config_->section(SECTION_RPC_STARTUP).lines())
 
 1482        if (!jrReader.
parse(cmd, jvCommand))
 
 1484            JLOG(m_journal.fatal()) << 
"Couldn't parse entry in [" 
 1485                                    << SECTION_RPC_STARTUP << 
"]: '" << cmd;
 
 1488        if (!config_->quiet())
 
 1490            JLOG(m_journal.fatal())
 
 1491                << 
"Startup RPC: " << jvCommand << 
std::endl;
 
 1497            {journal(
"RPCHandler"),
 
 1506             RPC::apiMaximumSupportedVersion},
 
 1510        RPC::doCommand(context, jvResult);
 
 1512        if (!config_->quiet())
 
 1514            JLOG(m_journal.fatal()) << 
"Result: " << jvResult << 
std::endl;
 
 1518    validatorSites_->start();
 
 
 1524ApplicationImp::start(
bool withTimers)
 
 1526    JLOG(m_journal.info()) << 
"Application starting. Version is " 
 1527                           << BuildInfo::getVersionString();
 
 1535    m_io_latency_sampler.start();
 
 1536    m_resolver->start();
 
 1537    m_loadManager->start();
 
 1538    m_shaMapStore->start();
 
 1542    if (grpcServer_->start())
 
 1544            *config_, {{SECTION_PORT_GRPC, grpcServer_->getEndpoint()}});
 
 1546    ledgerCleaner_->start();
 
 
 1551ApplicationImp::run()
 
 1553    if (!config_->standalone())
 
 1559        getLoadManager().activateStallDetector();
 
 1564        stoppingCondition_.wait(lk, [
this] { 
return isTimeToStop.load(); });
 
 1567    JLOG(m_journal.debug()) << 
"Application stopping";
 
 1569    m_io_latency_sampler.cancel_async();
 
 1577    m_io_latency_sampler.cancel();
 
 1579    m_resolver->stop_async();
 
 1589            sweepTimer_.cancel();
 
 1591        catch (boost::system::system_error 
const& e)
 
 1593            JLOG(m_journal.error())
 
 1594                << 
"Application: sweepTimer cancel error: " << e.what();
 
 1599            entropyTimer_.cancel();
 
 1601        catch (boost::system::system_error 
const& e)
 
 1603            JLOG(m_journal.error())
 
 1604                << 
"Application: entropyTimer cancel error: " << e.what();
 
 1610    using namespace std::chrono_literals;
 
 1612    waitHandlerCounter_.join(
"Application", 1s, m_journal);
 
 1614    mValidations.flush();
 
 1616    validatorSites_->stop();
 
 1619    validatorManifests_->save(
 
 1620        getWalletDB(), 
"ValidatorManifests", [
this](
PublicKey const& pubKey) {
 
 1621            return validators().listed(pubKey);
 
 1624    publisherManifests_->save(
 
 1625        getWalletDB(), 
"PublisherManifests", [
this](
PublicKey const& pubKey) {
 
 1626            return validators().trustedPublisher(pubKey);
 
 1631    m_loadManager->stop();
 
 1632    m_shaMapStore->stop();
 
 1636    grpcServer_->stop();
 
 1637    m_networkOPs->stop();
 
 1638    serverHandler_->stop();
 
 1639    m_ledgerReplayer->stop();
 
 1640    m_inboundTransactions->stop();
 
 1641    m_inboundLedgers->stop();
 
 1642    ledgerCleaner_->stop();
 
 1643    m_nodeStore->stop();
 
 1646    JLOG(m_journal.info()) << 
"Done.";
 
 
 1652    if (!isTimeToStop.exchange(
true))
 
 1655            JLOG(m_journal.warn()) << 
"Server stopping";
 
 1657            JLOG(m_journal.warn()) << 
"Server stopping: " << msg;
 
 1659        stoppingCondition_.notify_all();
 
 
 1664ApplicationImp::checkSigs()
 const 
 
 1670ApplicationImp::checkSigs(
bool check)
 
 
 1676ApplicationImp::isStopping()
 const 
 1678    return isTimeToStop.load();
 
 
 1682ApplicationImp::fdRequired()
 const 
 1689        needed += 2 * overlay_->limit();
 
 1693    needed += 
std::max(5, m_shaMapStore->fdRequired());
 
 1697    for (
auto const& p : serverHandler_->setup().ports)
 
 
 1707ApplicationImp::startGenesisLedger()
 
 1710        (config_->START_UP == Config::FRESH) ? m_amendmentTable->getDesired()
 
 1715    m_ledgerMaster->storeLedger(genesis);
 
 1719    next->updateSkipList();
 
 1721        next->info().seq < XRP_LEDGER_EARLIEST_FEES ||
 
 1722            next->read(keylet::fees()),
 
 1723        "ripple::ApplicationImp::startGenesisLedger : valid ledger fees");
 
 1724    next->setImmutable();
 
 1725    openLedger_.emplace(next, cachedSLEs_, logs_->journal(
"OpenLedger"));
 
 1726    m_ledgerMaster->storeLedger(next);
 
 1727    m_ledgerMaster->switchLCL(next);
 
 
 1731ApplicationImp::getLastFullLedger()
 
 1733    auto j = journal(
"Ledger");
 
 1743            ledger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
 
 1744                ledger->read(keylet::fees()),
 
 1745            "ripple::ApplicationImp::getLastFullLedger : valid ledger fees");
 
 1746        ledger->setImmutable();
 
 1748        if (getLedgerMaster().haveLedger(seq))
 
 1749            ledger->setValidated();
 
 1751        if (ledger->info().hash == 
hash)
 
 1753            JLOG(j.trace()) << 
"Loaded ledger: " << 
hash;
 
 1757        if (
auto stream = j.error())
 
 1759            stream << 
"Failed on ledger";
 
 1761            addJson(p, {*ledger, 
nullptr, LedgerFill::full});
 
 1769        JLOG(j.warn()) << 
"Ledger in database: " << mn.
what();
 
 
 1783            JLOG(m_journal.fatal()) << 
"Unable to open file '" << name << 
"'";
 
 1790        if (!reader.
parse(ledgerFile, jLedger))
 
 1792            JLOG(m_journal.fatal()) << 
"Unable to parse ledger JSON";
 
 1799        if (ledger.
get().isMember(
"result"))
 
 1800            ledger = ledger.
get()[
"result"];
 
 1802        if (ledger.
get().isMember(
"ledger"))
 
 1803            ledger = ledger.
get()[
"ledger"];
 
 1806        auto closeTime = timeKeeper().closeTime();
 
 1807        using namespace std::chrono_literals;
 
 1808        auto closeTimeResolution = 30s;
 
 1809        bool closeTimeEstimated = 
false;
 
 1812        if (ledger.
get().isMember(
"accountState"))
 
 1814            if (ledger.
get().isMember(jss::ledger_index))
 
 1816                seq = ledger.
get()[jss::ledger_index].asUInt();
 
 1819            if (ledger.
get().isMember(
"close_time"))
 
 1822                using d = tp::duration;
 
 1823                closeTime = tp{d{ledger.
get()[
"close_time"].asUInt()}};
 
 1825            if (ledger.
get().isMember(
"close_time_resolution"))
 
 1828                closeTimeResolution =
 
 1829                    seconds{ledger.
get()[
"close_time_resolution"].asUInt()};
 
 1831            if (ledger.
get().isMember(
"close_time_estimated"))
 
 1833                closeTimeEstimated =
 
 1834                    ledger.
get()[
"close_time_estimated"].asBool();
 
 1836            if (ledger.
get().isMember(
"total_coins"))
 
 1838                totalDrops = beast::lexicalCastThrow<std::uint64_t>(
 
 1839                    ledger.
get()[
"total_coins"].asString());
 
 1842            ledger = ledger.
get()[
"accountState"];
 
 1845        if (!ledger.
get().isArrayOrNull())
 
 1847            JLOG(m_journal.fatal()) << 
"State nodes must be an array";
 
 1853        loadLedger->setTotalDrops(totalDrops);
 
 1855        for (
Json::UInt index = 0; index < ledger.
get().size(); ++index)
 
 1861                JLOG(m_journal.fatal()) << 
"Invalid entry in ledger";
 
 1869                JLOG(m_journal.fatal()) << 
"Invalid entry in ledger";
 
 1879                JLOG(m_journal.fatal()) << 
"Invalid entry in ledger";
 
 1887            if (!loadLedger->addSLE(sle))
 
 1889                JLOG(m_journal.fatal())
 
 1890                    << 
"Couldn't add serialized ledger: " << uIndex;
 
 1898            loadLedger->info().seq < XRP_LEDGER_EARLIEST_FEES ||
 
 1899                loadLedger->read(keylet::fees()),
 
 1900            "ripple::ApplicationImp::loadLedgerFromFile : valid ledger fees");
 
 1901        loadLedger->setAccepted(
 
 1902            closeTime, closeTimeResolution, !closeTimeEstimated);
 
 1908        JLOG(m_journal.fatal()) << 
"Ledger contains invalid data: " << x.
what();
 
 
 1914ApplicationImp::loadOldLedger(
 
 1926            if (!ledgerID.
empty())
 
 1927                loadLedger = loadLedgerFromFile(ledgerID);
 
 1929        else if (ledgerID.
length() == 64)
 
 1933            if (
hash.parseHex(ledgerID))
 
 1944                        InboundLedger::Reason::GENERIC,
 
 1947                    if (il->checkLocal())
 
 1948                        loadLedger = il->getLedger();
 
 1952        else if (ledgerID.
empty() || boost::iequals(ledgerID, 
"latest"))
 
 1954            loadLedger = getLastFullLedger();
 
 1973            replayLedger = loadLedger;
 
 1975            JLOG(m_journal.info()) << 
"Loading parent ledger";
 
 1977            loadLedger = 
loadByHash(replayLedger->info().parentHash, *
this);
 
 1980                JLOG(m_journal.info())
 
 1981                    << 
"Loading parent ledger from node store";
 
 1986                    replayLedger->info().parentHash,
 
 1988                    InboundLedger::Reason::GENERIC,
 
 1992                if (il->checkLocal())
 
 1993                    loadLedger = il->getLedger();
 
 1998                    JLOG(m_journal.fatal()) << 
"Replay ledger missing/damaged";
 
 2000                        "ripple::ApplicationImp::loadOldLedger : replay ledger " 
 2007        using namespace std::chrono_literals;
 
 2008        using namespace date;
 
 2011        if (loadLedger->info().closeTime < ledgerWarnTimePoint)
 
 2013            JLOG(m_journal.fatal())
 
 2014                << 
"\n\n***  WARNING   ***\n" 
 2015                   "You are replaying a ledger from before " 
 2016                << to_string(ledgerWarnTimePoint)
 
 2018                   "This replay will not handle your ledger as it was " 
 2020                   "handled.\nConsider running an earlier version of rippled " 
 2022                   "get the older rules.\n*** CONTINUING ***\n";
 
 2025        JLOG(m_journal.info()) << 
"Loading ledger " << loadLedger->info().hash
 
 2026                               << 
" seq:" << loadLedger->info().seq;
 
 2028        if (loadLedger->info().accountHash.isZero())
 
 2031            JLOG(m_journal.fatal()) << 
"Ledger is empty.";
 
 2033                "ripple::ApplicationImp::loadOldLedger : ledger is empty");
 
 2038        if (!loadLedger->walkLedger(journal(
"Ledger"), 
true))
 
 2041            JLOG(m_journal.fatal()) << 
"Ledger is missing nodes.";
 
 2043                "ripple::ApplicationImp::loadOldLedger : ledger is missing " 
 2049        if (!loadLedger->assertSensible(journal(
"Ledger")))
 
 2052            JLOG(m_journal.fatal()) << 
"Ledger is not sensible.";
 
 2054                "ripple::ApplicationImp::loadOldLedger : ledger is not " 
 2060        m_ledgerMaster->setLedgerRangePresent(
 
 2061            loadLedger->info().seq, loadLedger->info().seq);
 
 2063        m_ledgerMaster->switchLCL(loadLedger);
 
 2064        loadLedger->setValidated();
 
 2065        m_ledgerMaster->setFullLedger(loadLedger, 
true, 
false);
 
 2066        openLedger_.emplace(
 
 2067            loadLedger, cachedSLEs_, logs_->journal(
"OpenLedger"));
 
 2076            for (
auto const& [_, tx] : replayData->orderedTxns())
 
 2079                auto txID = tx->getTransactionID();
 
 2080                if (trapTxID == txID)
 
 2083                    JLOG(m_journal.debug()) << 
"Trap transaction set: " << txID;
 
 2089                forceValidity(getHashRouter(), txID, Validity::SigGoodOnly);
 
 2091                openLedger_->modify(
 
 2098            m_ledgerMaster->takeReplay(std::move(replayData));
 
 2100            if (trapTxID && !trapTxID_)
 
 2102                JLOG(m_journal.fatal())
 
 2103                    << 
"Ledger " << replayLedger->info().seq
 
 2104                    << 
" does not contain the transaction hash " << *trapTxID;
 
 2111        JLOG(m_journal.fatal())
 
 2112            << 
"While loading specified ledger: " << mn.
what();
 
 2115    catch (boost::bad_lexical_cast&)
 
 2117        JLOG(m_journal.fatal())
 
 2118            << 
"Ledger specified '" << ledgerID << 
"' is not valid";
 
 
 2128    if (!config().ELB_SUPPORT)
 
 2133        reason = 
"Server is shutting down";
 
 2137    if (getOPs().isNeedNetworkLedger())
 
 2139        reason = 
"Not synchronized with network yet";
 
 2143    if (getOPs().isAmendmentBlocked())
 
 2145        reason = 
"Server version too old";
 
 2149    if (getOPs().isUNLBlocked())
 
 2151        reason = 
"No valid validator list available";
 
 2155    if (getOPs().getOperatingMode() < OperatingMode::SYNCING)
 
 2157        reason = 
"Not synchronized with network";
 
 2161    if (!getLedgerMaster().isCaughtUp(reason))
 
 2164    if (getFeeTrack().isLoadedLocal())
 
 2166        reason = 
"Too much load";
 
 
 2176    return logs_->journal(name);
 
 
 2180ApplicationImp::setMaxDisallowedLedger()
 
 2182    auto seq = getRelationalDatabase().getMaxLedgerSeq();
 
 2184        maxDisallowedLedger_ = *seq;
 
 2186    JLOG(m_journal.trace())
 
 2187        << 
"Max persisted ledger is " << maxDisallowedLedger_;
 
 
 2205        std::move(config), std::move(logs), std::move(timeKeeper));
 
 
 2211    for (
auto const& [name, ep] : endpoints)
 
 2213        if (!config.
exists(name))
 
 2216        auto& section = config[name];
 
 2217        auto const optPort = section.get(
"port");
 
 2221                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
 
io_latency_sampler(beast::insight::Event ev, beast::Journal journal, std::chrono::milliseconds interval, boost::asio::io_context &ios)
 
std::atomic< std::chrono::milliseconds > lastSample_
 
beast::io_latency_probe< std::chrono::steady_clock > m_probe
 
std::chrono::milliseconds get() const
 
void operator()(Duration const &elapsed)
 
std::unique_ptr< TxQ > txQ_
 
RCLValidations & getValidations() override
 
virtual ServerHandler & getServerHandler() override
 
std::unique_ptr< Cluster > cluster_
 
Config & config() override
 
std::unique_ptr< ValidatorList > validators_
 
std::uint64_t const instanceCookie_
 
HashRouter & getHashRouter() override
 
OrderBookDB & getOrderBookDB() override
 
std::unique_ptr< PeerReservationTable > peerReservations_
 
LoadFeeTrack & getFeeTrack() override
 
std::unique_ptr< Config > config_
 
Family & getNodeFamily() override
 
RCLValidations mValidations
 
std::optional< OpenLedger > openLedger_
 
std::unique_ptr< ResolverAsio > m_resolver
 
AmendmentTable & getAmendmentTable() override
 
io_latency_sampler m_io_latency_sampler
 
static std::size_t numberOfThreads(Config const &config)
 
bool isStopping() const override
 
LoadManager & getLoadManager() override
 
OrderBookDB m_orderBookDB
 
std::unique_ptr< LoadFeeTrack > mFeeTrack
 
boost::asio::steady_timer entropyTimer_
 
std::unique_ptr< LedgerCleaner > ledgerCleaner_
 
std::unique_ptr< NodeStore::Database > m_nodeStore
 
std::unique_ptr< PathRequests > m_pathRequests
 
std::unique_ptr< ManifestCache > validatorManifests_
 
LedgerIndex getMaxDisallowedLedger() override
Ensure that a newly-started validator does not sign proposals older than the last ledger it persisted...
 
ManifestCache & validatorManifests() override
 
OpenLedger const & openLedger() const override
 
std::unique_ptr< SHAMapStore > m_shaMapStore
 
std::unique_ptr< RelationalDatabase > mRelationalDatabase
 
std::pair< PublicKey, SecretKey > const & nodeIdentity() override
 
boost::asio::io_context & getIOContext() override
 
Overlay & overlay() override
 
ValidatorList & validators() override
 
ValidatorSite & validatorSites() override
 
virtual std::optional< uint256 > const & trapTxID() const override
 
PeerReservationTable & peerReservations() override
 
ManifestCache & publisherManifests() override
 
int fdRequired() const override
 
Application::MutexType & getMasterMutex() override
 
std::unique_ptr< LedgerMaster > m_ledgerMaster
 
TransactionMaster & getMasterTransaction() override
 
CollectorManager & getCollectorManager() override
 
NodeCache & getTempNodeCache() override
 
std::unique_ptr< InboundTransactions > m_inboundTransactions
 
std::unique_ptr< NetworkOPs > m_networkOPs
 
TransactionMaster m_txMaster
 
std::unique_ptr< InboundLedgers > m_inboundLedgers
 
std::unique_ptr< Overlay > overlay_
 
std::unique_ptr< HashRouter > hashRouter_
 
RelationalDatabase & getRelationalDatabase() override
 
bool serverOkay(std::string &reason) override
 
OpenLedger & openLedger() override
 
std::mutex stoppingMutex_
 
TimeKeeper & timeKeeper() override
 
std::optional< PublicKey const > getValidationPublicKey() const override
 
std::unique_ptr< ValidatorSite > validatorSites_
 
std::unique_ptr< CollectorManager > m_collectorManager
 
SHAMapStore & getSHAMapStore() override
 
InboundLedgers & getInboundLedgers() override
 
NodeCache m_tempNodeCache
 
InboundTransactions & getInboundTransactions() override
 
ClosureCounter< void, boost::system::error_code const  & > waitHandlerCounter_
 
void signalStop(std::string msg) override
 
Cluster & cluster() override
 
NodeStoreScheduler m_nodeStoreScheduler
 
LedgerReplayer & getLedgerReplayer() override
 
std::unique_ptr< ServerHandler > serverHandler_
 
LedgerMaster & getLedgerMaster() override
 
void gotTXSet(std::shared_ptr< SHAMap > const &set, bool fromAcquire)
 
void start(bool withTimers) override
 
std::unique_ptr< ManifestCache > publisherManifests_
 
boost::asio::signal_set m_signals
 
std::unique_ptr< LoadManager > m_loadManager
 
perf::PerfLog & getPerfLog() override
 
DatabaseCon & getWalletDB() override
Retrieve the "wallet database".
 
std::unique_ptr< GRPCServer > grpcServer_
 
Application::MutexType m_masterMutex
 
std::unique_ptr< perf::PerfLog > perfLog_
 
bool initRelationalDatabase()
 
bool checkSigs() const override
 
std::unique_ptr< TimeKeeper > timeKeeper_
 
NodeStore::Database & getNodeStore() override
 
PendingSaves & pendingSaves() override
 
std::unique_ptr< AmendmentTable > m_amendmentTable
 
std::optional< uint256 > trapTxID_
 
ApplicationImp(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
 
std::unique_ptr< DatabaseCon > mWalletDB
 
beast::Journal journal(std::string const &name) override
 
PathRequests & getPathRequests() override
 
std::optional< std::pair< PublicKey, SecretKey > > nodeIdentity_
 
boost::asio::steady_timer sweepTimer_
 
std::uint64_t instanceID() const override
Returns a 64-bit instance identifier, generated at startup.
 
std::unique_ptr< Resource::Manager > m_resourceManager
 
std::unique_ptr< LedgerReplayer > m_ledgerReplayer
 
CachedSLEs & cachedSLEs() override
 
std::chrono::milliseconds getIOLatency() override
 
LedgerCleaner & getLedgerCleaner() override
 
JobQueue & getJobQueue() override
 
ValidatorKeys const validatorKeys_
 
std::condition_variable stoppingCondition_
 
std::unique_ptr< Logs > logs_
 
Resource::Manager & getResourceManager() override
 
std::unique_ptr< JobQueue > m_jobQueue
 
std::atomic< bool > checkSigs_
 
PendingSaves pendingSaves_
 
bool setup(boost::program_options::variables_map const &cmdline) override
 
std::atomic< bool > isTimeToStop
 
TaggedCache< uint256, AcceptedLedger > & getAcceptedLedgerCache() override
 
NetworkOPs & getOPs() override
 
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
 
TaggedCache< uint256, AcceptedLedger > m_acceptedLedgerCache
 
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 peforms the tasks synchronously.
 
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.
 
static Manager & instance()
Returns the instance of the manager singleton.
 
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::tuple< std::shared_ptr< Ledger >, std::uint32_t, uint256 > getLatestLedger(Application &app)
 
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)
 
constexpr auto megabytes(T value) noexcept
 
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
 
DatabaseCon::Setup setup_DatabaseCon(Config const &c, std::optional< beast::Journal > j=std::nullopt)
 
std::unique_ptr< LedgerCleaner > make_LedgerCleaner(Application &app, beast::Journal journal)
 
TxQ::Setup setup_TxQ(Config const &config)
Build a TxQ::Setup object from application configuration.
 
std::shared_ptr< Ledger > loadByIndex(std::uint32_t ledgerIndex, Application &app, bool acquire)
 
std::unique_ptr< LoadManager > make_LoadManager(Application &app, beast::Journal journal)
 
std::unique_ptr< Application > make_Application(std::unique_ptr< Config > config, std::unique_ptr< Logs > logs, std::unique_ptr< TimeKeeper > timeKeeper)
 
void initAccountIdCache(std::size_t count)
Initialize the global cache used to map AccountID to base58 conversions.
 
std::unordered_map< std::string, boost::asio::ip::tcp::endpoint > Endpoints
 
std::pair< PublicKey, SecretKey > getNodeIdentity(Application &app, boost::program_options::variables_map const &cmdline)
The cryptographic credentials identifying this server instance.
 
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
 
csprng_engine & crypto_prng()
The default cryptographically secure PRNG.
 
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
 
std::shared_ptr< Ledger > loadByHash(uint256 const &ledgerHash, Application &app, bool acquire)
 
void addJson(Json::Value &json, LedgerFill const &fill)
Given a Ledger and options, fill a Json::Object or Json::Value with a description of the ledger.
 
std::unique_ptr< CollectorManager > make_CollectorManager(Section const ¶ms, beast::Journal journal)
 
std::unique_ptr< InboundTransactions > make_InboundTransactions(Application &app, beast::insight::Collector::ptr const &collector, std::function< void(std::shared_ptr< SHAMap > const &, bool)> gotSet)
 
std::unique_ptr< InboundLedgers > make_InboundLedgers(Application &app, InboundLedgers::clock_type &clock, beast::insight::Collector::ptr const &collector)
 
ServerHandler::Setup setup_ServerHandler(Config const &config, std::ostream &&log)
 
HashRouter::Setup setup_HashRouter(Config const &config)
 
Stopwatch & stopwatch()
Returns an instance of a wall clock.
 
std::optional< uint256 > getRegisteredFeature(std::string const &name)
 
std::unique_ptr< DatabaseCon > makeWalletDB(DatabaseCon::Setup const &setup, beast::Journal j)
makeWalletDB Opens the wallet database and returns it.
 
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
 
std::unique_ptr< ServerHandler > make_ServerHandler(Application &app, boost::asio::io_context &io_context, JobQueue &jobQueue, NetworkOPs &networkOPs, Resource::Manager &resourceManager, CollectorManager &cm)
 
create_genesis_t const create_genesis
 
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 void fixConfigPorts(Config &config, Endpoints const &endpoints)
 
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)
 
Overlay::Setup setup_Overlay(BasicConfig const &config)
 
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
 
std::unique_ptr< SHAMapStore > make_SHAMapStore(Application &app, NodeStore::Scheduler &scheduler, beast::Journal journal)
 
static std::string importNodeDatabase()