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/LedgerMaster.h> 
   24#include <xrpld/app/ledger/TransactionMaster.h> 
   25#include <xrpld/app/misc/HashRouter.h> 
   26#include <xrpld/app/misc/LoadFeeTrack.h> 
   27#include <xrpld/app/misc/NetworkOPs.h> 
   28#include <xrpld/app/misc/Transaction.h> 
   29#include <xrpld/app/misc/ValidatorList.h> 
   30#include <xrpld/app/tx/apply.h> 
   31#include <xrpld/overlay/Cluster.h> 
   32#include <xrpld/overlay/detail/PeerImp.h> 
   33#include <xrpld/overlay/detail/Tuning.h> 
   34#include <xrpld/perflog/PerfLog.h> 
   36#include <xrpl/basics/UptimeClock.h> 
   37#include <xrpl/basics/base64.h> 
   38#include <xrpl/basics/random.h> 
   39#include <xrpl/basics/safe_cast.h> 
   40#include <xrpl/protocol/TxFlags.h> 
   41#include <xrpl/protocol/digest.h> 
   43#include <boost/algorithm/string/predicate.hpp> 
   44#include <boost/beast/core/ostream.hpp> 
   53using namespace std::chrono_literals;
 
   87    , prefix_(makePrefix(fingerprint_))
 
   88    , sink_(app_.journal(
"Peer"), prefix_)
 
   89    , p_sink_(app_.journal(
"Protocol"), prefix_)
 
   92    , stream_ptr_(
std::move(stream_ptr))
 
   93    , socket_(stream_ptr_->next_layer().socket())
 
   94    , stream_(*stream_ptr_)
 
   95    , strand_(
boost::asio::make_strand(socket_.get_executor()))
 
   97    , remote_address_(slot->remote_endpoint())
 
  103    , publicKey_(publicKey)
 
  106    , squelch_(app_.journal(
"Squelch"))
 
  108    , fee_{Resource::feeTrivialPeer, 
""}
 
  110    , request_(
std::move(request))
 
  112    , compressionEnabled_(
 
  117              app_.config().COMPRESSION)
 
  123          app_.config().TX_REDUCE_RELAY_ENABLE))
 
  127          app_.config().LEDGER_REPLAY))
 
  128    , ledgerReplayMsgHandler_(app, app.getLedgerReplayer())
 
  132        << 
" vp reduce-relay base squelch enabled " 
 
  142    bool const inCluster{
cluster()};
 
 
  165    if (!
strand_.running_in_this_thread())
 
  168    auto parseLedgerHash =
 
  182    if (
auto const iter = 
headers_.find(
"Closed-Ledger");
 
  185        closed = parseLedgerHash(iter->value());
 
  188            fail(
"Malformed handshake data (1)");
 
  191    if (
auto const iter = 
headers_.find(
"Previous-Ledger");
 
  194        previous = parseLedgerHash(iter->value());
 
  197            fail(
"Malformed handshake data (2)");
 
  200    if (previous && !closed)
 
  201        fail(
"Malformed handshake data (3)");
 
 
  223    if (!
strand_.running_in_this_thread())
 
 
  243    if (!
strand_.running_in_this_thread())
 
  253    auto validator = m->getValidatorKey();
 
  254    if (validator && !
squelch_.expireSquelch(*validator))
 
  264        safe_cast<TrafficCount::category>(m->getCategory()),
 
  285        sink << n << 
" sendq: " << sendq_size;
 
  294    boost::asio::async_write(
 
  303                std::placeholders::_1,
 
  304                std::placeholders::_2)));
 
 
  310    if (!
strand_.running_in_this_thread())
 
  316        protocol::TMHaveTransactions ht;
 
  318            ht.add_hashes(hash.data(), hash.size());
 
 
  329    if (!
strand_.running_in_this_thread())
 
 
  346    if (!
strand_.running_in_this_thread())
 
  351    auto removed = 
txQueue_.erase(hash);
 
 
  363        fail(
"charge: Resources");
 
 
  372    auto const iter = 
headers_.find(
"Crawl");
 
  375    return boost::iequals(iter->value(), 
"public");
 
 
  401        ret[jss::inbound] = 
true;
 
  405        ret[jss::cluster] = 
true;
 
  415    if (
auto const nid = 
headers_[
"Network-ID"]; !nid.empty())
 
  432        std::chrono::duration_cast<std::chrono::seconds>(
uptime()).count());
 
  437    if ((minSeq != 0) || (maxSeq != 0))
 
  438        ret[jss::complete_ledgers] =
 
  444            ret[jss::track] = 
"diverged";
 
  448            ret[jss::track] = 
"unknown";
 
  457    protocol::TMStatusChange last_status;
 
  464    if (closedLedgerHash != beast::zero)
 
  465        ret[jss::ledger] = 
to_string(closedLedgerHash);
 
  467    if (last_status.has_newstatus())
 
  469        switch (last_status.newstatus())
 
  471            case protocol::nsCONNECTING:
 
  472                ret[jss::status] = 
"connecting";
 
  475            case protocol::nsCONNECTED:
 
  476                ret[jss::status] = 
"connected";
 
  479            case protocol::nsMONITORING:
 
  480                ret[jss::status] = 
"monitoring";
 
  483            case protocol::nsVALIDATING:
 
  484                ret[jss::status] = 
"validating";
 
  487            case protocol::nsSHUTTING:
 
  488                ret[jss::status] = 
"shutting";
 
  493                    << 
"Unknown status: " << last_status.newstatus();
 
  498    ret[jss::metrics][jss::total_bytes_recv] =
 
  500    ret[jss::metrics][jss::total_bytes_sent] =
 
  502    ret[jss::metrics][jss::avg_bps_recv] =
 
  504    ret[jss::metrics][jss::avg_bps_sent] =
 
 
  583        strand_.running_in_this_thread(),
 
  584        "ripple::PeerImp::fail : strand in this thread");
 
 
  597    if (!
strand_.running_in_this_thread())
 
 
  622        strand_.running_in_this_thread(),
 
  623        "ripple::PeerImp::tryAsyncShutdown : strand in this thread");
 
  636    stream_.async_shutdown(bind_executor(
 
 
  646        strand_.running_in_this_thread(),
 
  647        "ripple::PeerImp::shutdown: strand in this thread");
 
  654    boost::beast::get_lowest_layer(
stream_).cancel();
 
 
  671            (ec != boost::asio::error::eof &&
 
  672             ec != boost::asio::error::operation_aborted &&
 
  673             ec.message().find(
"application data after close notify") ==
 
 
  689        strand_.running_in_this_thread(),
 
  690        "ripple::PeerImp::close : strand in this thread");
 
 
  716        timer_.expires_after(interval);
 
  724    timer_.async_wait(bind_executor(
 
 
  744        strand_.running_in_this_thread(),
 
  745        "ripple::PeerImp::onTimer : strand in this thread");
 
  753        if (ec == boost::asio::error::operation_aborted)
 
  770        return fail(
"Large send queue");
 
  774        clock_type::duration duration;
 
  787            return fail(
"Not useful");
 
  793        return fail(
"Ping Timeout");
 
  798    protocol::TMPing message;
 
  799    message.set_type(protocol::TMPing::ptPING);
 
 
  826        "ripple::PeerImp::doAccept : empty read buffer");
 
  839        return fail(
"makeSharedValue: Unexpected failure");
 
  871    boost::asio::async_write(
 
  873        write_buffer->data(),
 
  874        boost::asio::transfer_all(),
 
  881                if (ec == boost::asio::error::operation_aborted)
 
  884                    return fail(
"onWriteResponse", ec);
 
  885                if (write_buffer->size() == bytes_transferred)
 
  887                return fail(
"Failed to write header");
 
 
  954        strand_.running_in_this_thread(),
 
  955        "ripple::PeerImp::onReadMessage : strand in this thread");
 
  964        if (ec == boost::asio::error::eof)
 
  970        if (ec == boost::asio::error::operation_aborted)
 
  973        return fail(
"onReadMessage", ec);
 
  981        stream << 
"onReadMessage: " 
  982               << (bytes_transferred > 0
 
  983                       ? 
to_string(bytes_transferred) + 
" bytes" 
  987    metrics_.recv.add_message(bytes_transferred);
 
  997        using namespace std::chrono_literals;
 
 1002            "invokeProtocolMessage",
 
 1012            return fail(
"onReadMessage", ec);
 
 1014        if (bytes_consumed == 0)
 
 1037                std::placeholders::_1,
 
 1038                std::placeholders::_2)));
 
 
 1045        strand_.running_in_this_thread(),
 
 1046        "ripple::PeerImp::onWriteMessage : strand in this thread");
 
 1055        if (ec == boost::asio::error::operation_aborted)
 
 1058        return fail(
"onWriteMessage", ec);
 
 1063        stream << 
"onWriteMessage: " 
 1064               << (bytes_transferred > 0
 
 1065                       ? 
to_string(bytes_transferred) + 
" bytes" 
 1069    metrics_.sent.add_message(bytes_transferred);
 
 1073        "ripple::PeerImp::onWriteMessage : non-empty send buffer");
 
 1084            "ripple::PeerImp::onWriteMessage : shutdown started");
 
 1087        return boost::asio::async_write(
 
 1089            boost::asio::buffer(
 
 1096                    std::placeholders::_1,
 
 1097                    std::placeholders::_2)));
 
 
 1126        *m, 
static_cast<protocol::MessageType
>(type), 
true);
 
 1136    if ((type == MessageType::mtTRANSACTION ||
 
 1137         type == MessageType::mtHAVE_TRANSACTIONS ||
 
 1138         type == MessageType::mtTRANSACTIONS ||
 
 1150            static_cast<MessageType
>(type), 
static_cast<std::uint64_t>(size));
 
 1152    JLOG(
journal_.
trace()) << 
"onMessageBegin: " << type << 
" " << size << 
" " 
 1153                           << uncompressed_size << 
" " << isCompressed;
 
 
 1168    auto const s = m->list_size();
 
 
 1188    if (m->type() == protocol::TMPing::ptPING)
 
 1192        m->set_type(protocol::TMPing::ptPONG);
 
 1197    if (m->type() == protocol::TMPing::ptPONG && m->has_seq())
 
 1207            auto const rtt = std::chrono::round<std::chrono::milliseconds>(
 
 
 1232    for (
int i = 0; i < m->clusternodes().size(); ++i)
 
 1234        protocol::TMClusterNode 
const& node = m->clusternodes(i);
 
 1237        if (node.has_nodename())
 
 1238            name = node.nodename();
 
 1240        auto const publicKey =
 
 1247            auto const reportTime =
 
 1251                *publicKey, 
name, node.nodeload(), reportTime);
 
 1255    int loadSources = m->loadsources().size();
 
 1256    if (loadSources != 0)
 
 1259        gossip.
items.reserve(loadSources);
 
 1260        for (
int i = 0; i < m->loadsources().size(); ++i)
 
 1262            protocol::TMLoadSource 
const& node = m->loadsources(i);
 
 1267                gossip.
items.push_back(item);
 
 1280        if (status.getReportTime() >= thresh)
 
 1281            fees.push_back(status.getLoadFee());
 
 1286        auto const index = fees.size() / 2;
 
 1288        clusterFee = fees[index];
 
 
 1304    if (m->endpoints_v2().size() >= 1024)
 
 1311    endpoints.
reserve(m->endpoints_v2().size());
 
 1314    for (
auto const& tm : m->endpoints_v2())
 
 1321                                     << tm.endpoint() << 
"}";
 
 1347    if (!endpoints.
empty())
 
 
 1364        eraseTxQueue != 
batch,
 
 1365        (
"ripple::PeerImp::handleTransaction : valid inputs"));
 
 1374                                 << 
"Need network ledger";
 
 1383        uint256 txID = stx->getTransactionID();
 
 1390            JLOG(
p_journal_.
warn()) << 
"Ignoring Network relayed Tx containing " 
 1391                                       "tfInnerBatchTxn (handleTransaction).";
 
 1423        bool checkSignature = 
true;
 
 1426            if (!m->has_deferred() || !m->deferred())
 
 1439                checkSignature = 
false;
 
 1446                << 
"No new transactions until synchronized";
 
 1459                "recvTransaction->checkTransaction",
 
 1465                    if (
auto peer = weak.lock())
 
 1466                        peer->checkTransaction(
 
 1467                            flags, checkSignature, stx, 
batch);
 
 1474            << 
"Transaction invalid: " << 
strHex(m->rawtransaction())
 
 1475            << 
". Exception: " << ex.
what();
 
 
 1486    auto const itype{m->itype()};
 
 1489    if (itype < protocol::liBASE || itype > protocol::liTS_CANDIDATE)
 
 1490        return badData(
"Invalid ledger info type");
 
 1498    if (itype == protocol::liTS_CANDIDATE)
 
 1500        if (!m->has_ledgerhash())
 
 1501            return badData(
"Invalid TX candidate set, missing TX set hash");
 
 1504        !m->has_ledgerhash() && !m->has_ledgerseq() &&
 
 1505        !(ltype && *ltype == protocol::ltCLOSED))
 
 1507        return badData(
"Invalid request");
 
 1511    if (ltype && (*ltype < protocol::ltACCEPTED || *ltype > protocol::ltCLOSED))
 
 1512        return badData(
"Invalid ledger type");
 
 1516        return badData(
"Invalid ledger hash");
 
 1519    if (m->has_ledgerseq())
 
 1521        auto const ledgerSeq{m->ledgerseq()};
 
 1524        using namespace std::chrono_literals;
 
 1534    if (itype != protocol::liBASE)
 
 1536        if (m->nodeids_size() <= 0)
 
 1537            return badData(
"Invalid ledger node IDs");
 
 1539        for (
auto const& nodeId : m->nodeids())
 
 1542                return badData(
"Invalid SHAMap node ID");
 
 1547    if (m->has_querytype() && m->querytype() != protocol::qtINDIRECT)
 
 1548        return badData(
"Invalid query type");
 
 1551    if (m->has_querydepth())
 
 1554            itype == protocol::liBASE)
 
 1556            return badData(
"Invalid query depth");
 
 1563        if (
auto peer = weak.
lock())
 
 1564            peer->processLedgerRequest(m);
 
 
 1584            if (
auto peer = weak.
lock())
 
 1587                    peer->ledgerReplayMsgHandler_.processProofPathRequest(m);
 
 1588                if (reply.has_error())
 
 1590                    if (reply.error() == protocol::TMReplyError::reBAD_REQUEST)
 
 1592                            Resource::feeMalformedRequest,
 
 1593                            "proof_path_request");
 
 1596                            Resource::feeRequestNoReply, 
"proof_path_request");
 
 1600                    peer->send(std::make_shared<Message>(
 
 1601                        reply, protocol::mtPROOF_PATH_RESPONSE));
 
 
 1610    if (!ledgerReplayEnabled_)
 
 1613            Resource::feeMalformedRequest, 
"proof_path_response disabled");
 
 1617    if (!ledgerReplayMsgHandler_.processProofPathResponse(m))
 
 1619        fee_.update(Resource::feeInvalidData, 
"proof_path_response");
 
 
 1626    JLOG(p_journal_.trace()) << 
"onMessage, TMReplayDeltaRequest";
 
 1627    if (!ledgerReplayEnabled_)
 
 1630            Resource::feeMalformedRequest, 
"replay_delta_request disabled");
 
 1634    fee_.fee = Resource::feeModerateBurdenPeer;
 
 1636    app_.getJobQueue().addJob(
 
 1638            if (
auto peer = weak.
lock())
 
 1641                    peer->ledgerReplayMsgHandler_.processReplayDeltaRequest(m);
 
 1642                if (reply.has_error())
 
 1644                    if (reply.error() == protocol::TMReplyError::reBAD_REQUEST)
 
 1646                            Resource::feeMalformedRequest,
 
 1647                            "replay_delta_request");
 
 1650                            Resource::feeRequestNoReply,
 
 1651                            "replay_delta_request");
 
 1655                    peer->send(std::make_shared<Message>(
 
 1656                        reply, protocol::mtREPLAY_DELTA_RESPONSE));
 
 
 1665    if (!ledgerReplayEnabled_)
 
 1668            Resource::feeMalformedRequest, 
"replay_delta_response disabled");
 
 1672    if (!ledgerReplayMsgHandler_.processReplayDeltaResponse(m))
 
 1674        fee_.update(Resource::feeInvalidData, 
"replay_delta_response");
 
 
 1682        fee_.update(Resource::feeInvalidData, msg);
 
 1683        JLOG(p_journal_.warn()) << 
"TMLedgerData: " << msg;
 
 1688        return badData(
"Invalid ledger hash");
 
 1692        auto const ledgerSeq{m->ledgerseq()};
 
 1693        if (m->type() == protocol::liTS_CANDIDATE)
 
 1704            using namespace std::chrono_literals;
 
 1705            if (app_.getLedgerMaster().getValidatedLedgerAge() <= 10s &&
 
 1706                ledgerSeq > app_.getLedgerMaster().getValidLedgerIndex() + 10)
 
 1715    if (m->type() < protocol::liBASE || m->type() > protocol::liTS_CANDIDATE)
 
 1716        return badData(
"Invalid ledger info type");
 
 1719    if (m->has_error() &&
 
 1720        (m->error() < protocol::reNO_LEDGER ||
 
 1721         m->error() > protocol::reBAD_REQUEST))
 
 1723        return badData(
"Invalid reply error");
 
 1727    if (m->nodes_size() <= 0 || m->nodes_size() > Tuning::hardMaxReplyNodes)
 
 1730            "Invalid Ledger/TXset nodes " + 
std::to_string(m->nodes_size()));
 
 1734    if (m->has_requestcookie())
 
 1736        if (
auto peer = overlay_.findPeerByShortID(m->requestcookie()))
 
 1738            m->clear_requestcookie();
 
 1743            JLOG(p_journal_.info()) << 
"Unable to route TX/ledger data reply";
 
 1748    uint256 const ledgerHash{m->ledgerhash()};
 
 1751    if (m->type() == protocol::liTS_CANDIDATE)
 
 1754        app_.getJobQueue().addJob(
 
 1755            jtTXN_DATA, 
"recvPeerData", [weak, ledgerHash, m]() {
 
 1756                if (
auto peer = weak.lock())
 
 1758                    peer->app_.getInboundTransactions().gotData(
 
 1759                        ledgerHash, peer, m);
 
 1766    app_.getInboundLedgers().gotLedgerData(ledgerHash, shared_from_this(), m);
 
 
 1772    protocol::TMProposeSet& 
set = *m;
 
 1781        JLOG(p_journal_.warn()) << 
"Proposal: malformed";
 
 1783            Resource::feeInvalidSignature,
 
 1784            " signature can't be longer than 72 bytes");
 
 1791        JLOG(p_journal_.warn()) << 
"Proposal: malformed";
 
 1792        fee_.update(Resource::feeMalformedRequest, 
"bad hashes");
 
 1800    auto const isTrusted = app_.validators().trusted(publicKey);
 
 1808        overlay_.reportInboundTraffic(
 
 1809            TrafficCount::category::proposal_untrusted,
 
 1810            Message::messageSize(*m));
 
 1812        if (app_.config().RELAY_UNTRUSTED_PROPOSALS == -1)
 
 1816    uint256 const proposeHash{
set.currenttxhash()};
 
 1817    uint256 const prevLedger{
set.previousledger()};
 
 1829    if (
auto [added, relayed] =
 
 1830            app_.getHashRouter().addSuppressionPeerWithStatus(suppression, id_);
 
 1835        if (relayed && (
stopwatch().now() - *relayed) < reduce_relay::IDLED)
 
 1836            overlay_.updateSlotAndSquelch(
 
 1837                suppression, publicKey, id_, protocol::mtPROPOSE_LEDGER);
 
 1840        overlay_.reportInboundTraffic(
 
 1841            TrafficCount::category::proposal_duplicate,
 
 1842            Message::messageSize(*m));
 
 1844        JLOG(p_journal_.trace()) << 
"Proposal: duplicate";
 
 1851        if (tracking_.load() == Tracking::diverged)
 
 1853            JLOG(p_journal_.debug())
 
 1854                << 
"Proposal: Dropping untrusted (peer divergence)";
 
 1858        if (!cluster() && app_.getFeeTrack().isLoadedLocal())
 
 1860            JLOG(p_journal_.debug()) << 
"Proposal: Dropping untrusted (load)";
 
 1865    JLOG(p_journal_.trace())
 
 1866        << 
"Proposal: " << (isTrusted ? 
"trusted" : 
"untrusted");
 
 1877            app_.timeKeeper().closeTime(),
 
 1878            calcNodeID(app_.validatorManifests().getMasterKey(publicKey))});
 
 1881    app_.getJobQueue().addJob(
 
 1883        "recvPropose->checkPropose",
 
 1885            if (
auto peer = weak.lock())
 
 1886                peer->checkPropose(isTrusted, m, 
proposal);
 
 
 1893    JLOG(p_journal_.trace()) << 
"Status: Change";
 
 1895    if (!m->has_networktime())
 
 1896        m->set_networktime(app_.timeKeeper().now().time_since_epoch().count());
 
 1900        if (!last_status_.has_newstatus() || m->has_newstatus())
 
 1905            protocol::NodeStatus status = last_status_.newstatus();
 
 1907            m->set_newstatus(status);
 
 1911    if (m->newevent() == protocol::neLOST_SYNC)
 
 1913        bool outOfSync{
false};
 
 1918            if (!closedLedgerHash_.isZero())
 
 1921                closedLedgerHash_.zero();
 
 1923            previousLedgerHash_.zero();
 
 1927            JLOG(p_journal_.debug()) << 
"Status: Out of sync";
 
 1934        bool const peerChangedLedgers{
 
 1941            if (peerChangedLedgers)
 
 1943                closedLedgerHash_ = m->ledgerhash();
 
 1944                closedLedgerHash = closedLedgerHash_;
 
 1945                addLedger(closedLedgerHash, sl);
 
 1949                closedLedgerHash_.zero();
 
 1952            if (m->has_ledgerhashprevious() &&
 
 1955                previousLedgerHash_ = m->ledgerhashprevious();
 
 1956                addLedger(previousLedgerHash_, sl);
 
 1960                previousLedgerHash_.zero();
 
 1963        if (peerChangedLedgers)
 
 1965            JLOG(p_journal_.debug()) << 
"LCL is " << closedLedgerHash;
 
 1969            JLOG(p_journal_.debug()) << 
"Status: No ledger";
 
 1973    if (m->has_firstseq() && m->has_lastseq())
 
 1977        minLedger_ = m->firstseq();
 
 1978        maxLedger_ = m->lastseq();
 
 1980        if ((maxLedger_ < minLedger_) || (minLedger_ == 0) || (maxLedger_ == 0))
 
 1981            minLedger_ = maxLedger_ = 0;
 
 1984    if (m->has_ledgerseq() &&
 
 1985        app_.getLedgerMaster().getValidatedLedgerAge() < 2min)
 
 1988            m->ledgerseq(), app_.getLedgerMaster().getValidLedgerIndex());
 
 1991    app_.getOPs().pubPeerStatus([=, 
this]() -> 
Json::Value {
 
 1994        if (m->has_newstatus())
 
 1996            switch (m->newstatus())
 
 1998                case protocol::nsCONNECTING:
 
 1999                    j[jss::status] = 
"CONNECTING";
 
 2001                case protocol::nsCONNECTED:
 
 2002                    j[jss::status] = 
"CONNECTED";
 
 2004                case protocol::nsMONITORING:
 
 2005                    j[jss::status] = 
"MONITORING";
 
 2007                case protocol::nsVALIDATING:
 
 2008                    j[jss::status] = 
"VALIDATING";
 
 2010                case protocol::nsSHUTTING:
 
 2011                    j[jss::status] = 
"SHUTTING";
 
 2016        if (m->has_newevent())
 
 2018            switch (m->newevent())
 
 2020                case protocol::neCLOSING_LEDGER:
 
 2021                    j[jss::action] = 
"CLOSING_LEDGER";
 
 2023                case protocol::neACCEPTED_LEDGER:
 
 2024                    j[jss::action] = 
"ACCEPTED_LEDGER";
 
 2026                case protocol::neSWITCHED_LEDGER:
 
 2027                    j[jss::action] = 
"SWITCHED_LEDGER";
 
 2029                case protocol::neLOST_SYNC:
 
 2030                    j[jss::action] = 
"LOST_SYNC";
 
 2035        if (m->has_ledgerseq())
 
 2037            j[jss::ledger_index] = m->ledgerseq();
 
 2040        if (m->has_ledgerhash())
 
 2042            uint256 closedLedgerHash{};
 
 2045                closedLedgerHash = closedLedgerHash_;
 
 2047            j[jss::ledger_hash] = to_string(closedLedgerHash);
 
 2050        if (m->has_networktime())
 
 2055        if (m->has_firstseq() && m->has_lastseq())
 
 2057            j[jss::ledger_index_min] = 
Json::UInt(m->firstseq());
 
 2058            j[jss::ledger_index_max] = 
Json::UInt(m->lastseq());
 
 
 2074        serverSeq = maxLedger_;
 
 2080        checkTracking(serverSeq, validationSeq);
 
 
 2089    if (diff < Tuning::convergedLedgerLimit)
 
 2092        tracking_ = Tracking::converged;
 
 2095    if ((diff > Tuning::divergedLedgerLimit) &&
 
 2096        (tracking_.load() != Tracking::diverged))
 
 2101        tracking_ = Tracking::diverged;
 
 2102        trackingTime_ = clock_type::now();
 
 
 2111        fee_.update(Resource::feeMalformedRequest, 
"bad hash");
 
 2115    uint256 const hash{m->hash()};
 
 2117    if (m->status() == protocol::tsHAVE)
 
 2121        if (
std::find(recentTxSets_.begin(), recentTxSets_.end(), hash) !=
 
 2122            recentTxSets_.end())
 
 2124            fee_.update(Resource::feeUselessData, 
"duplicate (tsHAVE)");
 
 2128        recentTxSets_.push_back(hash);
 
 
 2133PeerImp::onValidatorListMessage(
 
 2143        JLOG(p_journal_.warn()) << 
"Ignored malformed " << messageType;
 
 2145        fee_.update(Resource::feeHeavyBurdenPeer, 
"no blobs");
 
 2151    JLOG(p_journal_.debug()) << 
"Received " << messageType;
 
 2153    if (!app_.getHashRouter().addSuppressionPeer(hash, id_))
 
 2155        JLOG(p_journal_.debug())
 
 2156            << messageType << 
": received duplicate " << messageType;
 
 2160        fee_.update(Resource::feeUselessData, 
"duplicate");
 
 2164    auto const applyResult = app_.validators().applyListsAndBroadcast(
 
 2168        remote_address_.to_string(),
 
 2171        app_.getHashRouter(),
 
 2174    JLOG(p_journal_.debug())
 
 2175        << 
"Processed " << messageType << 
" version " << version << 
" from " 
 2176        << (applyResult.publisherKey ? 
strHex(*applyResult.publisherKey)
 
 2177                                     : 
"unknown or invalid publisher")
 
 2178        << 
" with best result " << to_string(applyResult.bestDisposition());
 
 2181    switch (applyResult.bestDisposition())
 
 2184        case ListDisposition::accepted:
 
 2186        case ListDisposition::expired:
 
 2188        case ListDisposition::pending: {
 
 2192                applyResult.publisherKey,
 
 2193                "ripple::PeerImp::onValidatorListMessage : publisher key is " 
 2195            auto const& pubKey = *applyResult.publisherKey;
 
 2197            if (
auto const iter = publisherListSequences_.find(pubKey);
 
 2198                iter != publisherListSequences_.end())
 
 2201                    iter->second < applyResult.sequence,
 
 2202                    "ripple::PeerImp::onValidatorListMessage : lower sequence");
 
 2205            publisherListSequences_[pubKey] = applyResult.sequence;
 
 2208        case ListDisposition::same_sequence:
 
 2209        case ListDisposition::known_sequence:
 
 2214                applyResult.sequence && applyResult.publisherKey,
 
 2215                "ripple::PeerImp::onValidatorListMessage : nonzero sequence " 
 2216                "and set publisher key");
 
 2218                publisherListSequences_[*applyResult.publisherKey] <=
 
 2219                    applyResult.sequence,
 
 2220                "ripple::PeerImp::onValidatorListMessage : maximum sequence");
 
 2225        case ListDisposition::stale:
 
 2226        case ListDisposition::untrusted:
 
 2227        case ListDisposition::invalid:
 
 2228        case ListDisposition::unsupported_version:
 
 2233                "ripple::PeerImp::onValidatorListMessage : invalid best list " 
 2239    switch (applyResult.worstDisposition())
 
 2241        case ListDisposition::accepted:
 
 2242        case ListDisposition::expired:
 
 2243        case ListDisposition::pending:
 
 2246        case ListDisposition::same_sequence:
 
 2247        case ListDisposition::known_sequence:
 
 2252                Resource::feeUselessData,
 
 2253                " duplicate (same_sequence or known_sequence)");
 
 2255        case ListDisposition::stale:
 
 2258            fee_.update(Resource::feeInvalidData, 
"expired");
 
 2260        case ListDisposition::untrusted:
 
 2264            fee_.update(Resource::feeUselessData, 
"untrusted");
 
 2266        case ListDisposition::invalid:
 
 2269                Resource::feeInvalidSignature, 
"invalid list disposition");
 
 2271        case ListDisposition::unsupported_version:
 
 2274            fee_.update(Resource::feeInvalidData, 
"version");
 
 2279                "ripple::PeerImp::onValidatorListMessage : invalid worst list " 
 2285    for (
auto const& [disp, count] : applyResult.dispositions)
 
 2290            case ListDisposition::accepted:
 
 2291                JLOG(p_journal_.debug())
 
 2292                    << 
"Applied " << count << 
" new " << messageType;
 
 2295            case ListDisposition::expired:
 
 2296                JLOG(p_journal_.debug())
 
 2297                    << 
"Applied " << count << 
" expired " << messageType;
 
 2300            case ListDisposition::pending:
 
 2301                JLOG(p_journal_.debug())
 
 2302                    << 
"Processed " << count << 
" future " << messageType;
 
 2304            case ListDisposition::same_sequence:
 
 2305                JLOG(p_journal_.warn())
 
 2306                    << 
"Ignored " << count << 
" " << messageType
 
 2307                    << 
"(s) with current sequence";
 
 2309            case ListDisposition::known_sequence:
 
 2310                JLOG(p_journal_.warn())
 
 2311                    << 
"Ignored " << count << 
" " << messageType
 
 2312                    << 
"(s) with future sequence";
 
 2314            case ListDisposition::stale:
 
 2315                JLOG(p_journal_.warn())
 
 2316                    << 
"Ignored " << count << 
"stale " << messageType;
 
 2318            case ListDisposition::untrusted:
 
 2319                JLOG(p_journal_.warn())
 
 2320                    << 
"Ignored " << count << 
" untrusted " << messageType;
 
 2322            case ListDisposition::unsupported_version:
 
 2323                JLOG(p_journal_.warn())
 
 2324                    << 
"Ignored " << count << 
"unsupported version " 
 2327            case ListDisposition::invalid:
 
 2328                JLOG(p_journal_.warn())
 
 2329                    << 
"Ignored " << count << 
"invalid " << messageType;
 
 2334                    "ripple::PeerImp::onValidatorListMessage : invalid list " 
 
 2346        if (!supportsFeature(ProtocolFeature::ValidatorListPropagation))
 
 2348            JLOG(p_journal_.debug())
 
 2349                << 
"ValidatorList: received validator list from peer using " 
 2350                << 
"protocol version " << to_string(protocol_)
 
 2351                << 
" which shouldn't support this feature.";
 
 2352            fee_.update(Resource::feeUselessData, 
"unsupported peer");
 
 2355        onValidatorListMessage(
 
 2359            ValidatorList::parseBlobs(*m));
 
 2363        JLOG(p_journal_.warn()) << 
"ValidatorList: Exception, " << e.
what();
 
 2364        using namespace std::string_literals;
 
 2365        fee_.update(Resource::feeInvalidData, e.
what());
 
 
 2375        if (!supportsFeature(ProtocolFeature::ValidatorList2Propagation))
 
 2377            JLOG(p_journal_.debug())
 
 2378                << 
"ValidatorListCollection: received validator list from peer " 
 2379                << 
"using protocol version " << to_string(protocol_)
 
 2380                << 
" which shouldn't support this feature.";
 
 2381            fee_.update(Resource::feeUselessData, 
"unsupported peer");
 
 2384        else if (m->version() < 2)
 
 2386            JLOG(p_journal_.debug())
 
 2387                << 
"ValidatorListCollection: received invalid validator list " 
 2389                << m->version() << 
" from peer using protocol version " 
 2390                << to_string(protocol_);
 
 2391            fee_.update(Resource::feeInvalidData, 
"wrong version");
 
 2394        onValidatorListMessage(
 
 2395            "ValidatorListCollection",
 
 2398            ValidatorList::parseBlobs(*m));
 
 2402        JLOG(p_journal_.warn())
 
 2403            << 
"ValidatorListCollection: Exception, " << e.
what();
 
 2404        using namespace std::string_literals;
 
 2405        fee_.update(Resource::feeInvalidData, e.
what());
 
 
 2412    if (m->validation().size() < 50)
 
 2414        JLOG(p_journal_.warn()) << 
"Validation: Too small";
 
 2415        fee_.update(Resource::feeMalformedRequest, 
"too small");
 
 2421        auto const closeTime = app_.timeKeeper().closeTime();
 
 2430                        app_.validatorManifests().getMasterKey(pk));
 
 2433            val->setSeen(closeTime);
 
 2437                app_.getValidations().parms(),
 
 2438                app_.timeKeeper().closeTime(),
 
 2440                val->getSeenTime()))
 
 2442            JLOG(p_journal_.trace()) << 
"Validation: Not current";
 
 2443            fee_.update(Resource::feeUselessData, 
"not current");
 
 2450        auto const isTrusted =
 
 2451            app_.validators().trusted(val->getSignerPublic());
 
 2459            overlay_.reportInboundTraffic(
 
 2460                TrafficCount::category::validation_untrusted,
 
 2461                Message::messageSize(*m));
 
 2463            if (app_.config().RELAY_UNTRUSTED_VALIDATIONS == -1)
 
 2469        auto [added, relayed] =
 
 2470            app_.getHashRouter().addSuppressionPeerWithStatus(key, id_);
 
 2477            if (relayed && (
stopwatch().now() - *relayed) < reduce_relay::IDLED)
 
 2478                overlay_.updateSlotAndSquelch(
 
 2479                    key, val->getSignerPublic(), id_, protocol::mtVALIDATION);
 
 2482            overlay_.reportInboundTraffic(
 
 2483                TrafficCount::category::validation_duplicate,
 
 2484                Message::messageSize(*m));
 
 2486            JLOG(p_journal_.trace()) << 
"Validation: duplicate";
 
 2490        if (!isTrusted && (tracking_.load() == Tracking::diverged))
 
 2492            JLOG(p_journal_.debug())
 
 2493                << 
"Dropping untrusted validation from diverged peer";
 
 2495        else if (isTrusted || !app_.getFeeTrack().isLoadedLocal())
 
 2499                    isTrusted ? 
"Trusted validation" : 
"Untrusted validation";
 
 2504                    to_string(val->getNodeID());
 
 2511            app_.getJobQueue().addJob(
 
 2514                [weak, val, m, key]() {
 
 2515                    if (
auto peer = weak.
lock())
 
 2516                        peer->checkValidation(val, key, m);
 
 2521            JLOG(p_journal_.debug())
 
 2522                << 
"Dropping untrusted validation for load";
 
 2527        JLOG(p_journal_.warn())
 
 2528            << 
"Exception processing validation: " << e.
what();
 
 2529        using namespace std::string_literals;
 
 2530        fee_.update(Resource::feeMalformedRequest, e.
what());
 
 
 2537    protocol::TMGetObjectByHash& packet = *m;
 
 2539    JLOG(p_journal_.trace()) << 
"received TMGetObjectByHash " << packet.type()
 
 2540                             << 
" " << packet.objects_size();
 
 2545        if (send_queue_.size() >= Tuning::dropSendQueue)
 
 2547            JLOG(p_journal_.debug()) << 
"GetObject: Large send queue";
 
 2551        if (packet.type() == protocol::TMGetObjectByHash::otFETCH_PACK)
 
 2557        if (packet.type() == protocol::TMGetObjectByHash::otTRANSACTIONS)
 
 2559            if (!txReduceRelayEnabled())
 
 2561                JLOG(p_journal_.error())
 
 2562                    << 
"TMGetObjectByHash: tx reduce-relay is disabled";
 
 2563                fee_.update(Resource::feeMalformedRequest, 
"disabled");
 
 2568            app_.getJobQueue().addJob(
 
 2570                    if (
auto peer = weak.
lock())
 
 2571                        peer->doTransactions(m);
 
 2576        protocol::TMGetObjectByHash reply;
 
 2578        reply.set_query(
false);
 
 2580        if (packet.has_seq())
 
 2581            reply.set_seq(packet.seq());
 
 2583        reply.set_type(packet.type());
 
 2585        if (packet.has_ledgerhash())
 
 2589                fee_.update(Resource::feeMalformedRequest, 
"ledger hash");
 
 2593            reply.set_ledgerhash(packet.ledgerhash());
 
 2597            Resource::feeModerateBurdenPeer,
 
 2598            " received a get object by hash request");
 
 2601        for (
int i = 0; i < packet.objects_size(); ++i)
 
 2603            auto const& obj = packet.objects(i);
 
 2606                uint256 const hash{obj.hash()};
 
 2609                std::uint32_t seq{obj.has_ledgerseq() ? obj.ledgerseq() : 0};
 
 2610                auto nodeObject{app_.getNodeStore().fetchNodeObject(hash, seq)};
 
 2613                    protocol::TMIndexedObject& newObj = *reply.add_objects();
 
 2614                    newObj.set_hash(hash.begin(), hash.size());
 
 2616                        &nodeObject->getData().front(),
 
 2617                        nodeObject->getData().size());
 
 2619                    if (obj.has_nodeid())
 
 2620                        newObj.set_index(obj.nodeid());
 
 2621                    if (obj.has_ledgerseq())
 
 2622                        newObj.set_ledgerseq(obj.ledgerseq());
 
 2629        JLOG(p_journal_.trace()) << 
"GetObj: " << reply.objects_size() << 
" of " 
 2630                                 << packet.objects_size();
 
 2638        bool progress = 
false;
 
 2640        for (
int i = 0; i < packet.objects_size(); ++i)
 
 2642            protocol::TMIndexedObject 
const& obj = packet.objects(i);
 
 2646                if (obj.has_ledgerseq())
 
 2648                    if (obj.ledgerseq() != pLSeq)
 
 2650                        if (pLDo && (pLSeq != 0))
 
 2652                            JLOG(p_journal_.debug())
 
 2653                                << 
"GetObj: Full fetch pack for " << pLSeq;
 
 2655                        pLSeq = obj.ledgerseq();
 
 2656                        pLDo = !app_.getLedgerMaster().haveLedger(pLSeq);
 
 2660                            JLOG(p_journal_.debug())
 
 2661                                << 
"GetObj: Late fetch pack for " << pLSeq;
 
 2670                    uint256 const hash{obj.hash()};
 
 2672                    app_.getLedgerMaster().addFetchPack(
 
 2675                            obj.data().begin(), obj.data().end()));
 
 2680        if (pLDo && (pLSeq != 0))
 
 2682            JLOG(p_journal_.debug())
 
 2683                << 
"GetObj: Partial fetch pack for " << pLSeq;
 
 2685        if (packet.type() == protocol::TMGetObjectByHash::otFETCH_PACK)
 
 2686            app_.getLedgerMaster().gotFetchPack(progress, pLSeq);
 
 
 2693    if (!txReduceRelayEnabled())
 
 2695        JLOG(p_journal_.error())
 
 2696            << 
"TMHaveTransactions: tx reduce-relay is disabled";
 
 2697        fee_.update(Resource::feeMalformedRequest, 
"disabled");
 
 2702    app_.getJobQueue().addJob(
 
 2704            if (
auto peer = weak.
lock())
 
 2705                peer->handleHaveTransactions(m);
 
 
 2710PeerImp::handleHaveTransactions(
 
 2713    protocol::TMGetObjectByHash tmBH;
 
 2714    tmBH.set_type(protocol::TMGetObjectByHash_ObjectType_otTRANSACTIONS);
 
 2715    tmBH.set_query(
true);
 
 2717    JLOG(p_journal_.trace())
 
 2718        << 
"received TMHaveTransactions " << m->hashes_size();
 
 2724            JLOG(p_journal_.error())
 
 2725                << 
"TMHaveTransactions with invalid hash size";
 
 2726            fee_.update(Resource::feeMalformedRequest, 
"hash size");
 
 2732        auto txn = app_.getMasterTransaction().fetch_from_cache(hash);
 
 2734        JLOG(p_journal_.trace()) << 
"checking transaction " << (bool)txn;
 
 2738            JLOG(p_journal_.debug()) << 
"adding transaction to request";
 
 2740            auto obj = tmBH.add_objects();
 
 2741            obj->set_hash(hash.
data(), hash.
size());
 
 2748            removeTxQueue(hash);
 
 2752    JLOG(p_journal_.trace())
 
 2753        << 
"transaction request object is " << tmBH.objects_size();
 
 2755    if (tmBH.objects_size() > 0)
 
 
 2762    if (!txReduceRelayEnabled())
 
 2764        JLOG(p_journal_.error())
 
 2765            << 
"TMTransactions: tx reduce-relay is disabled";
 
 2766        fee_.update(Resource::feeMalformedRequest, 
"disabled");
 
 2770    JLOG(p_journal_.trace())
 
 2771        << 
"received TMTransactions " << m->transactions_size();
 
 2773    overlay_.addTxMetrics(m->transactions_size());
 
 2778                m->mutable_transactions(i), [](protocol::TMTransaction*) {}),
 
 
 2786    using on_message_fn =
 
 2788    if (!strand_.running_in_this_thread())
 
 2792                (on_message_fn)&PeerImp::onMessage, shared_from_this(), m));
 
 2794    if (!m->has_validatorpubkey())
 
 2796        fee_.update(Resource::feeInvalidData, 
"squelch no pubkey");
 
 2799    auto validator = m->validatorpubkey();
 
 2803        fee_.update(Resource::feeInvalidData, 
"squelch bad pubkey");
 
 2809    if (key == app_.getValidationPublicKey())
 
 2811        JLOG(p_journal_.debug())
 
 2812            << 
"onMessage: TMSquelch discarding validator's squelch " << slice;
 
 2817        m->has_squelchduration() ? m->squelchduration() : 0;
 
 2819        squelch_.removeSquelch(key);
 
 2821        fee_.update(Resource::feeInvalidData, 
"squelch duration");
 
 2823    JLOG(p_journal_.debug())
 
 2824        << 
"onMessage: TMSquelch " << slice << 
" " << id() << 
" " << duration;
 
 
 2836    (void)lockedRecentLock;
 
 2838    if (
std::find(recentLedgers_.begin(), recentLedgers_.end(), hash) !=
 
 2839        recentLedgers_.end())
 
 2842    recentLedgers_.push_back(hash);
 
 
 2851    if (app_.getFeeTrack().isLoadedLocal() ||
 
 2852        (app_.getLedgerMaster().getValidatedLedgerAge() > 40s) ||
 
 2853        (app_.getJobQueue().getJobCount(
jtPACK) > 10))
 
 2855        JLOG(p_journal_.info()) << 
"Too busy to make fetch pack";
 
 2861        JLOG(p_journal_.warn()) << 
"FetchPack hash size malformed";
 
 2862        fee_.update(Resource::feeMalformedRequest, 
"hash size");
 
 2866    fee_.fee = Resource::feeHeavyBurdenPeer;
 
 2868    uint256 const hash{packet->ledgerhash()};
 
 2871    auto elapsed = UptimeClock::now();
 
 2872    auto const pap = &app_;
 
 2873    app_.getJobQueue().addJob(
 
 2874        jtPACK, 
"MakeFetchPack", [pap, weak, packet, hash, elapsed]() {
 
 2875            pap->getLedgerMaster().makeFetchPack(weak, packet, hash, elapsed);
 
 
 2880PeerImp::doTransactions(
 
 2883    protocol::TMTransactions reply;
 
 2885    JLOG(p_journal_.trace()) << 
"received TMGetObjectByHash requesting tx " 
 2886                             << packet->objects_size();
 
 2888    if (packet->objects_size() > reduce_relay::MAX_TX_QUEUE_SIZE)
 
 2890        JLOG(p_journal_.error()) << 
"doTransactions, invalid number of hashes";
 
 2891        fee_.update(Resource::feeMalformedRequest, 
"too big");
 
 2897        auto const& obj = packet->objects(i);
 
 2901            fee_.update(Resource::feeMalformedRequest, 
"hash size");
 
 2907        auto txn = app_.getMasterTransaction().fetch_from_cache(hash);
 
 2911            JLOG(p_journal_.error()) << 
"doTransactions, transaction not found " 
 2913            fee_.update(Resource::feeMalformedRequest, 
"tx not found");
 
 2918        auto tx = reply.add_transactions();
 
 2919        auto sttx = txn->getSTransaction();
 
 2921        tx->set_rawtransaction(s.
data(), s.
size());
 
 2923            txn->getStatus() == 
INCLUDED ? protocol::tsCURRENT
 
 2925        tx->set_receivetimestamp(
 
 2926            app_.timeKeeper().now().time_since_epoch().count());
 
 2927        tx->set_deferred(txn->getSubmitResult().queued);
 
 2930    if (reply.transactions_size() > 0)
 
 
 2935PeerImp::checkTransaction(
 
 2937    bool checkSignature,
 
 2949            JLOG(p_journal_.warn()) << 
"Ignoring Network relayed Tx containing " 
 2950                                       "tfInnerBatchTxn (checkSignature).";
 
 2951            charge(Resource::feeModerateBurdenPeer, 
"inner batch txn");
 
 2957        if (stx->isFieldPresent(sfLastLedgerSequence) &&
 
 2958            (stx->getFieldU32(sfLastLedgerSequence) <
 
 2959             app_.getLedgerMaster().getValidLedgerIndex()))
 
 2961            JLOG(p_journal_.info())
 
 2962                << 
"Marking transaction " << stx->getTransactionID()
 
 2963                << 
"as BAD because it's expired";
 
 2964            app_.getHashRouter().setFlags(
 
 2965                stx->getTransactionID(), HashRouterFlags::BAD);
 
 2966            charge(Resource::feeUselessData, 
"expired tx");
 
 2977                tx->getStatus() == 
NEW,
 
 2978                "ripple::PeerImp::checkTransaction Transaction created " 
 2980            if (tx->getStatus() == 
NEW)
 
 2982                JLOG(p_journal_.debug())
 
 2983                    << 
"Processing " << (
batch ? 
"batch" : 
"unsolicited")
 
 2984                    << 
" pseudo-transaction tx " << tx->getID();
 
 2986                app_.getMasterTransaction().canonicalize(&tx);
 
 2989                    app_.getHashRouter().shouldRelay(tx->getID());
 
 2992                    JLOG(p_journal_.debug())
 
 2993                        << 
"Passing skipped pseudo pseudo-transaction tx " 
 2995                    app_.overlay().relay(tx->getID(), {}, *toSkip);
 
 2999                    JLOG(p_journal_.debug())
 
 3000                        << 
"Charging for pseudo-transaction tx " << tx->getID();
 
 3001                    charge(Resource::feeUselessData, 
"pseudo tx");
 
 3012                    app_.getHashRouter(),
 
 3014                    app_.getLedgerMaster().getValidatedRules(),
 
 3016                valid != Validity::Valid)
 
 3018                if (!validReason.empty())
 
 3020                    JLOG(p_journal_.debug())
 
 3021                        << 
"Exception checking transaction: " << validReason;
 
 3026                app_.getHashRouter().setFlags(
 
 3027                    stx->getTransactionID(), HashRouterFlags::BAD);
 
 3029                    Resource::feeInvalidSignature,
 
 3030                    "check transaction signature failure");
 
 3037                app_.getHashRouter(), stx->getTransactionID(), Validity::Valid);
 
 3043        if (tx->getStatus() == 
INVALID)
 
 3045            if (!reason.
empty())
 
 3047                JLOG(p_journal_.debug())
 
 3048                    << 
"Exception checking transaction: " << reason;
 
 3050            app_.getHashRouter().setFlags(
 
 3051                stx->getTransactionID(), HashRouterFlags::BAD);
 
 3052            charge(Resource::feeInvalidSignature, 
"tx (impossible)");
 
 3056        bool const trusted = any(flags & HashRouterFlags::TRUSTED);
 
 3057        app_.getOPs().processTransaction(
 
 3058            tx, trusted, 
false, NetworkOPs::FailHard::no);
 
 3062        JLOG(p_journal_.warn())
 
 3063            << 
"Exception in " << __func__ << 
": " << ex.
what();
 
 3064        app_.getHashRouter().setFlags(
 
 3065            stx->getTransactionID(), HashRouterFlags::BAD);
 
 3066        using namespace std::string_literals;
 
 3067        charge(Resource::feeInvalidData, 
"tx "s + ex.
what());
 
 
 3073PeerImp::checkPropose(
 
 3078    JLOG(p_journal_.trace())
 
 3079        << 
"Checking " << (isTrusted ? 
"trusted" : 
"UNTRUSTED") << 
" proposal";
 
 3081    XRPL_ASSERT(packet, 
"ripple::PeerImp::checkPropose : non-null packet");
 
 3086        JLOG(p_journal_.warn()) << desc;
 
 3087        charge(Resource::feeInvalidSignature, desc);
 
 3094        relay = app_.getOPs().processTrustedProposal(peerPos);
 
 3096        relay = app_.config().RELAY_UNTRUSTED_PROPOSALS == 1 || cluster();
 
 3104        auto haveMessage = app_.overlay().relay(
 
 3106        if (!haveMessage.empty())
 
 3107            overlay_.updateSlotAndSquelch(
 
 3110                std::move(haveMessage),
 
 3111                protocol::mtPROPOSE_LEDGER);
 
 
 3116PeerImp::checkValidation(
 
 3121    if (!val->isValid())
 
 3123        std::string desc{
"Validation forwarded by peer is invalid"};
 
 3124        JLOG(p_journal_.debug()) << desc;
 
 3125        charge(Resource::feeInvalidSignature, desc);
 
 3140                overlay_.relay(*packet, key, val->getSignerPublic());
 
 3141            if (!haveMessage.empty())
 
 3143                overlay_.updateSlotAndSquelch(
 
 3145                    val->getSignerPublic(),
 
 3146                    std::move(haveMessage),
 
 3147                    protocol::mtVALIDATION);
 
 3153        JLOG(p_journal_.trace())
 
 3154            << 
"Exception processing validation: " << ex.
what();
 
 3155        using namespace std::string_literals;
 
 3156        charge(Resource::feeMalformedRequest, 
"validation "s + ex.
what());
 
 
 3170        if (p->hasTxSet(rootHash) && p.get() != skip)
 
 3172            auto score = p->getScore(true);
 
 3173            if (!ret || (score > retScore))
 
 
 3198        if (p->hasLedger(ledgerHash, ledger) && p.get() != skip)
 
 3200            auto score = p->getScore(true);
 
 3201            if (!ret || (score > retScore))
 
 
 3213PeerImp::sendLedgerBase(
 
 3215    protocol::TMLedgerData& ledgerData)
 
 3217    JLOG(p_journal_.trace()) << 
"sendLedgerBase: Base data";
 
 3220    addRaw(ledger->info(), s);
 
 3223    auto const& stateMap{ledger->stateMap()};
 
 3224    if (stateMap.getHash() != beast::zero)
 
 3229        stateMap.serializeRoot(
root);
 
 3230        ledgerData.add_nodes()->set_nodedata(
 
 3231            root.getDataPtr(), 
root.getLength());
 
 3233        if (ledger->info().txHash != beast::zero)
 
 3235            auto const& txMap{ledger->txMap()};
 
 3236            if (txMap.getHash() != beast::zero)
 
 3240                txMap.serializeRoot(
root);
 
 3241                ledgerData.add_nodes()->set_nodedata(
 
 3242                    root.getDataPtr(), 
root.getLength());
 
 
 3255    JLOG(p_journal_.trace()) << 
"getLedger: Ledger";
 
 3259    if (m->has_ledgerhash())
 
 3262        uint256 const ledgerHash{m->ledgerhash()};
 
 3263        ledger = app_.getLedgerMaster().getLedgerByHash(ledgerHash);
 
 3266            JLOG(p_journal_.trace())
 
 3267                << 
"getLedger: Don't have ledger with hash " << ledgerHash;
 
 3269            if (m->has_querytype() && !m->has_requestcookie())
 
 3275                        m->has_ledgerseq() ? m->ledgerseq() : 0,
 
 3278                    m->set_requestcookie(
id());
 
 3281                    JLOG(p_journal_.debug())
 
 3282                        << 
"getLedger: Request relayed to peer";
 
 3286                JLOG(p_journal_.trace())
 
 3287                    << 
"getLedger: Failed to find peer to relay request";
 
 3291    else if (m->has_ledgerseq())
 
 3294        if (m->ledgerseq() < app_.getLedgerMaster().getEarliestFetch())
 
 3296            JLOG(p_journal_.debug())
 
 3297                << 
"getLedger: Early ledger sequence request";
 
 3301            ledger = app_.getLedgerMaster().getLedgerBySeq(m->ledgerseq());
 
 3304                JLOG(p_journal_.debug())
 
 3305                    << 
"getLedger: Don't have ledger with sequence " 
 3310    else if (m->has_ltype() && m->ltype() == protocol::ltCLOSED)
 
 3312        ledger = app_.getLedgerMaster().getClosedLedger();
 
 3318        auto const ledgerSeq{ledger->info().seq};
 
 3319        if (m->has_ledgerseq())
 
 3321            if (ledgerSeq != m->ledgerseq())
 
 3324                if (!m->has_requestcookie())
 
 3326                        Resource::feeMalformedRequest, 
"get_ledger ledgerSeq");
 
 3329                JLOG(p_journal_.warn())
 
 3330                    << 
"getLedger: Invalid ledger sequence " << ledgerSeq;
 
 3333        else if (ledgerSeq < app_.getLedgerMaster().getEarliestFetch())
 
 3336            JLOG(p_journal_.debug())
 
 3337                << 
"getLedger: Early ledger sequence request " << ledgerSeq;
 
 3342        JLOG(p_journal_.debug()) << 
"getLedger: Unable to find ledger";
 
 
 3351    JLOG(p_journal_.trace()) << 
"getTxSet: TX set";
 
 3353    uint256 const txSetHash{m->ledgerhash()};
 
 3355        app_.getInboundTransactions().getSet(txSetHash, 
false)};
 
 3358        if (m->has_querytype() && !m->has_requestcookie())
 
 3363                m->set_requestcookie(
id());
 
 3366                JLOG(p_journal_.debug()) << 
"getTxSet: Request relayed";
 
 3370                JLOG(p_journal_.debug())
 
 3371                    << 
"getTxSet: Failed to find relay peer";
 
 3376            JLOG(p_journal_.debug()) << 
"getTxSet: Failed to find TX set";
 
 
 3387    if (!m->has_requestcookie())
 
 3389            Resource::feeModerateBurdenPeer, 
"received a get ledger request");
 
 3393    SHAMap const* map{
nullptr};
 
 3394    protocol::TMLedgerData ledgerData;
 
 3395    bool fatLeaves{
true};
 
 3396    auto const itype{m->itype()};
 
 3398    if (itype == protocol::liTS_CANDIDATE)
 
 3400        if (sharedMap = getTxSet(m); !sharedMap)
 
 3402        map = sharedMap.
get();
 
 3405        ledgerData.set_ledgerseq(0);
 
 3406        ledgerData.set_ledgerhash(m->ledgerhash());
 
 3407        ledgerData.set_type(protocol::liTS_CANDIDATE);
 
 3408        if (m->has_requestcookie())
 
 3409            ledgerData.set_requestcookie(m->requestcookie());
 
 3416        if (send_queue_.size() >= Tuning::dropSendQueue)
 
 3418            JLOG(p_journal_.debug())
 
 3419                << 
"processLedgerRequest: Large send queue";
 
 3422        if (app_.getFeeTrack().isLoadedLocal() && !cluster())
 
 3424            JLOG(p_journal_.debug()) << 
"processLedgerRequest: Too busy";
 
 3428        if (ledger = getLedger(m); !ledger)
 
 3432        auto const ledgerHash{ledger->info().hash};
 
 3433        ledgerData.set_ledgerhash(ledgerHash.begin(), ledgerHash.size());
 
 3434        ledgerData.set_ledgerseq(ledger->info().seq);
 
 3435        ledgerData.set_type(itype);
 
 3436        if (m->has_requestcookie())
 
 3437            ledgerData.set_requestcookie(m->requestcookie());
 
 3441            case protocol::liBASE:
 
 3442                sendLedgerBase(ledger, ledgerData);
 
 3445            case protocol::liTX_NODE:
 
 3446                map = &ledger->txMap();
 
 3447                JLOG(p_journal_.trace()) << 
"processLedgerRequest: TX map hash " 
 3448                                         << to_string(map->getHash());
 
 3451            case protocol::liAS_NODE:
 
 3452                map = &ledger->stateMap();
 
 3453                JLOG(p_journal_.trace())
 
 3454                    << 
"processLedgerRequest: Account state map hash " 
 3455                    << to_string(map->getHash());
 
 3460                JLOG(p_journal_.error())
 
 3461                    << 
"processLedgerRequest: Invalid ledger info type";
 
 3468        JLOG(p_journal_.warn()) << 
"processLedgerRequest: Unable to find map";
 
 3473    if (m->nodeids_size() > 0)
 
 3475        auto const queryDepth{
 
 3476            m->has_querydepth() ? m->querydepth() : (isHighLatency() ? 2 : 1)};
 
 3480        for (
int i = 0; i < m->nodeids_size() &&
 
 3481             ledgerData.nodes_size() < Tuning::softMaxReplyNodes;
 
 3487            data.reserve(Tuning::softMaxReplyNodes);
 
 3491                if (map->getNodeFat(*shaMapNodeId, data, fatLeaves, queryDepth))
 
 3493                    JLOG(p_journal_.trace())
 
 3494                        << 
"processLedgerRequest: getNodeFat got " 
 3495                        << data.size() << 
" nodes";
 
 3497                    for (
auto const& d : data)
 
 3499                        if (ledgerData.nodes_size() >=
 
 3500                            Tuning::hardMaxReplyNodes)
 
 3502                        protocol::TMLedgerNode* node{ledgerData.add_nodes()};
 
 3503                        node->set_nodeid(d.first.getRawString());
 
 3504                        node->set_nodedata(d.second.data(), d.second.size());
 
 3509                    JLOG(p_journal_.warn())
 
 3510                        << 
"processLedgerRequest: getNodeFat returns false";
 
 3518                    case protocol::liBASE:
 
 3520                        info = 
"Ledger base";
 
 3523                    case protocol::liTX_NODE:
 
 3527                    case protocol::liAS_NODE:
 
 3531                    case protocol::liTS_CANDIDATE:
 
 3532                        info = 
"TS candidate";
 
 3540                if (!m->has_ledgerhash())
 
 3541                    info += 
", no hash specified";
 
 3543                JLOG(p_journal_.warn())
 
 3544                    << 
"processLedgerRequest: getNodeFat with nodeId " 
 3545                    << *shaMapNodeId << 
" and ledger info type " << info
 
 3546                    << 
" throws exception: " << e.
what();
 
 3550        JLOG(p_journal_.info())
 
 3551            << 
"processLedgerRequest: Got request for " << m->nodeids_size()
 
 3552            << 
" nodes at depth " << queryDepth << 
", return " 
 3553            << ledgerData.nodes_size() << 
" nodes";
 
 3556    if (ledgerData.nodes_size() == 0)
 
 
 3563PeerImp::getScore(
bool haveItem)
 const 
 3567    static int const spRandomMax = 9999;
 
 3571    static int const spHaveItem = 10000;
 
 3576    static int const spLatency = 30;
 
 3579    static int const spNoLatency = 8000;
 
 3584        score += spHaveItem;
 
 3593        score -= latency->count() * spLatency;
 
 3595        score -= spNoLatency;
 
 
 3601PeerImp::isHighLatency()
 const 
 3604    return latency_ >= peerHighLatency;
 
 
 3610    using namespace std::chrono_literals;
 
 3613    totalBytes_ += bytes;
 
 3614    accumBytes_ += bytes;
 
 3615    auto const timeElapsed = clock_type::now() - intervalStart_;
 
 3616    auto const timeElapsedInSecs =
 
 3617        std::chrono::duration_cast<std::chrono::seconds>(timeElapsed);
 
 3619    if (timeElapsedInSecs >= 1s)
 
 3621        auto const avgBytes = accumBytes_ / timeElapsedInSecs.count();
 
 3622        rollingAvg_.push_back(avgBytes);
 
 3624        auto const totalBytes =
 
 3626        rollingAvgBytes_ = totalBytes / rollingAvg_.size();
 
 3628        intervalStart_ = clock_type::now();
 
 
 3634PeerImp::Metrics::average_bytes()
 const 
 3637    return rollingAvgBytes_;
 
 
 3641PeerImp::Metrics::total_bytes()
 const 
 
A version-independent IP address and port combination.
 
Address const & address() const
Returns the address portion of this endpoint.
 
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
 
Endpoint at_port(Port port) const
Returns a new Endpoint with a different port.
 
static Endpoint from_string(std::string const &s)
 
std::string to_string() const
Returns a string representing the endpoint.
 
bool active(Severity level) const
Returns true if any message would be logged at this severity level.
 
Stream trace() const
Severity stream access functions.
 
virtual Config & config()=0
 
virtual LoadFeeTrack & getFeeTrack()=0
 
virtual TimeKeeper & timeKeeper()=0
 
virtual JobQueue & getJobQueue()=0
 
virtual NetworkOPs & getOPs()=0
 
virtual ValidatorList & validators()=0
 
virtual std::optional< PublicKey const > getValidationPublicKey() const =0
 
virtual LedgerMaster & getLedgerMaster()=0
 
virtual Cluster & cluster()=0
 
virtual HashRouter & getHashRouter()=0
 
void for_each(std::function< void(ClusterNode const &)> func) const
Invokes the callback once for every cluster node.
 
std::size_t size() const
The number of nodes in the cluster list.
 
bool update(PublicKey const &identity, std::string name, std::uint32_t loadFee=0, NetClock::time_point reportTime=NetClock::time_point{})
Store information about the state of a cluster node.
 
std::optional< std::string > member(PublicKey const &node) const
Determines whether a node belongs in the cluster.
 
bool VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE
 
bool TX_REDUCE_RELAY_METRICS
 
std::chrono::seconds MAX_DIVERGED_TIME
 
std::chrono::seconds MAX_UNKNOWN_TIME
 
bool shouldProcess(uint256 const &key, PeerShortID peer, HashRouterFlags &flags, std::chrono::seconds tx_interval)
 
bool addSuppressionPeer(uint256 const &key, PeerShortID peer)
 
std::unique_ptr< LoadEvent > makeLoadEvent(JobType t, std::string const &name)
Return a scoped LoadEvent.
 
int getJobCount(JobType t) const
Jobs waiting at this priority.
 
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
 
LedgerIndex getValidLedgerIndex()
 
std::chrono::seconds getValidatedLedgerAge()
 
void setClusterFee(std::uint32_t fee)
 
static std::size_t messageSize(::google::protobuf::Message const &message)
 
virtual bool isNeedNetworkLedger()=0
 
PeerFinder::Manager & peerFinder()
 
void activate(std::shared_ptr< PeerImp > const &peer)
Called when a peer has connected successfully This is called after the peer handshake has been comple...
 
void deletePeer(Peer::id_t id)
Called when the peer is deleted.
 
void incPeerDisconnect() override
Increment and retrieve counters for total peer disconnects, and disconnects we initiate for excessive...
 
void addTxMetrics(Args... args)
Add tx reduce-relay metrics.
 
void onPeerDeactivate(Peer::id_t id)
 
void remove(std::shared_ptr< PeerFinder::Slot > const &slot)
 
void reportOutboundTraffic(TrafficCount::category cat, int bytes)
 
void for_each(UnaryFunc &&f) const
 
Resource::Manager & resourceManager()
 
void reportInboundTraffic(TrafficCount::category cat, int bytes)
 
void onManifests(std::shared_ptr< protocol::TMManifests > const &m, std::shared_ptr< PeerImp > const &from)
 
Setup const & setup() const
 
std::shared_ptr< Message > getManifestsMessage()
 
void incPeerDisconnectCharges() override
 
void incJqTransOverflow() override
Increment and retrieve counter for transaction job queue overflows.
 
virtual void on_endpoints(std::shared_ptr< Slot > const &slot, Endpoints const &endpoints)=0
Called when mtENDPOINTS is received.
 
virtual Config config()=0
Returns the configuration for the manager.
 
virtual void on_closed(std::shared_ptr< Slot > const &slot)=0
Called when the slot is closed.
 
virtual void on_failure(std::shared_ptr< Slot > const &slot)=0
Called when an outbound connection is deemed to have failed.
 
This class manages established peer-to-peer connections, handles message exchange,...
 
std::queue< std::shared_ptr< Message > > send_queue_
 
std::unique_ptr< LoadEvent > load_event_
 
boost::beast::http::fields const  & headers_
 
void onMessageEnd(std::uint16_t type, std::shared_ptr<::google::protobuf::Message > const &m)
 
bool hasLedger(uint256 const &hash, std::uint32_t seq) const override
 
clock_type::duration uptime() const
 
void removeTxQueue(uint256 const &hash) override
Remove transaction's hash from the transactions' hashes queue.
 
protocol::TMStatusChange last_status_
 
boost::circular_buffer< uint256 > recentTxSets_
 
std::unique_ptr< stream_type > stream_ptr_
 
void onMessage(std::shared_ptr< protocol::TMManifests > const &m)
 
Tracking
Whether the peer's view of the ledger converges or diverges from ours.
 
Compressed compressionEnabled_
 
uint256 closedLedgerHash_
 
std::string domain() const
 
std::optional< std::uint32_t > lastPingSeq_
 
std::string const & fingerprint() const override
 
beast::Journal const journal_
 
void tryAsyncShutdown()
Attempts to perform a graceful SSL shutdown if conditions are met.
 
beast::Journal const p_journal_
 
PeerImp(PeerImp const &)=delete
 
void shutdown()
Initiates the peer disconnection sequence.
 
bool hasRange(std::uint32_t uMin, std::uint32_t uMax) override
 
bool hasTxSet(uint256 const &hash) const override
 
clock_type::time_point lastPingTime_
 
void onMessageUnknown(std::uint16_t type)
 
std::shared_ptr< PeerFinder::Slot > const slot_
 
std::shared_mutex nameMutex_
 
boost::circular_buffer< uint256 > recentLedgers_
 
std::optional< std::chrono::milliseconds > latency_
 
void handleTransaction(std::shared_ptr< protocol::TMTransaction > const &m, bool eraseTxQueue, bool batch)
Called from onMessage(TMTransaction(s)).
 
beast::IP::Endpoint const remote_address_
 
Json::Value json() override
 
PublicKey const publicKey_
 
void close()
Forcibly closes the underlying socket connection.
 
hash_set< uint256 > txQueue_
 
void onMessageBegin(std::uint16_t type, std::shared_ptr<::google::protobuf::Message > const &m, std::size_t size, std::size_t uncompressed_size, bool isCompressed)
 
bool txReduceRelayEnabled_
 
void fail(std::string const &name, error_code ec)
Handles a failure associated with a specific error code.
 
clock_type::time_point trackingTime_
 
void cancelTimer() noexcept
Cancels any pending wait on the peer activity timer.
 
ProtocolVersion protocol_
 
reduce_relay::Squelch< UptimeClock > squelch_
 
std::string getVersion() const
Return the version of rippled that the peer is running, if reported.
 
struct ripple::PeerImp::@22 metrics_
 
uint256 previousLedgerHash_
 
void charge(Resource::Charge const &fee, std::string const &context) override
Adjust this peer's load balance based on the type of load imposed.
 
void onTimer(error_code const &ec)
Handles the expiration of the peer activity timer.
 
void send(std::shared_ptr< Message > const &m) override
 
boost::system::error_code error_code
 
void onReadMessage(error_code ec, std::size_t bytes_transferred)
 
bool ledgerReplayEnabled_
 
boost::asio::basic_waitable_timer< std::chrono::steady_clock > waitable_timer
 
bool crawl() const
Returns true if this connection will publicly share its IP address.
 
void setTimer(std::chrono::seconds interval)
Sets and starts the peer timer.
 
void sendTxQueue() override
Send aggregated transactions' hashes.
 
bool txReduceRelayEnabled() const override
 
bool supportsFeature(ProtocolFeature f) const override
 
void onWriteMessage(error_code ec, std::size_t bytes_transferred)
 
http_request_type request_
 
void addTxQueue(uint256 const &hash) override
Add transaction's hash to the transactions' hashes queue.
 
static std::string makePrefix(std::string const &fingerprint)
 
bool cluster() const override
Returns true if this connection is a member of the cluster.
 
void onShutdown(error_code ec)
Handles the completion of the asynchronous SSL shutdown.
 
boost::asio::strand< boost::asio::executor > strand_
 
void cycleStatus() override
 
boost::beast::multi_buffer read_buffer_
 
Resource::Consumer usage_
 
void ledgerRange(std::uint32_t &minSeq, std::uint32_t &maxSeq) const override
 
std::atomic< Tracking > tracking_
 
Represents a peer connection in the overlay.
 
A peer's signed, proposed position for use in RCLConsensus.
 
bool checkSign() const
Verify the signing hash of the proposal.
 
PublicKey const & publicKey() const
Public key of peer that sent the proposal.
 
uint256 const & suppressionID() const
Unique id used by hash router to suppress duplicates.
 
An endpoint that consumes resources.
 
int balance()
Returns the credit balance representing consumption.
 
bool disconnect(beast::Journal const &j)
Returns true if the consumer should be disconnected.
 
Disposition charge(Charge const &fee, std::string const &context={})
Apply a load charge to the consumer.
 
virtual void importConsumers(std::string const &origin, Gossip const &gossip)=0
Import packaged consumer information.
 
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
 
std::size_t size() const noexcept
 
void const * data() const noexcept
 
void const * getDataPtr() const
 
An immutable linear range of bytes.
 
time_point now() const override
Returns the current time, using the server's clock.
 
static category categorize(::google::protobuf::Message const &message, protocol::MessageType type, bool inbound)
Given a protocol message, determine which traffic category it belongs to.
 
static void sendValidatorList(Peer &peer, std::uint64_t peerSequence, PublicKey const &publisherKey, std::size_t maxSequence, std::uint32_t rawVersion, std::string const &rawManifest, std::map< std::size_t, ValidatorBlobInfo > const &blobInfos, HashRouter &hashRouter, beast::Journal j)
 
void for_each_available(std::function< void(std::string const &manifest, std::uint32_t version, std::map< std::size_t, ValidatorBlobInfo > const &blobInfos, PublicKey const &pubKey, std::size_t maxSequence, uint256 const &hash)> func) const
Invokes the callback once for every available publisher list's raw data members.
 
static constexpr std::size_t size()
 
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
 
T emplace_back(T... args)
 
@ objectValue
object value (collection of name/value pairs).
 
Charge const feeMalformedRequest
Schedule of fees charged for imposing load on the server.
 
Charge const feeInvalidData
 
Charge const feeUselessData
 
Charge const feeTrivialPeer
 
Charge const feeModerateBurdenPeer
 
std::size_t constexpr readBufferBytes
Size of buffer used to read from the socket.
 
@ targetSendQueue
How many messages we consider reasonable sustained on a send queue.
 
@ maxQueryDepth
The maximum number of levels to search.
 
@ sendqIntervals
How many timer intervals a sendq has to stay large before we disconnect.
 
@ sendQueueLogFreq
How often to log send queue size.
 
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
 
auto measureDurationAndLog(Func &&func, std::string const &actionDescription, std::chrono::duration< Rep, Period > maxDelay, beast::Journal const &journal)
 
static constexpr std::size_t MAX_TX_QUEUE_SIZE
 
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
 
std::string protocolMessageName(int type)
Returns the name of a protocol message given its type.
 
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
 
uint256 proposalUniqueId(uint256 const &proposeHash, uint256 const &previousLedger, std::uint32_t proposeSeq, NetClock::time_point closeTime, Slice const &publicKey, Slice const &signature)
Calculate a unique identifier for a signed proposal.
 
constexpr ProtocolVersion make_protocol(std::uint16_t major, std::uint16_t minor)
 
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
 
static constexpr char FEATURE_COMPR[]
 
std::optional< SHAMapNodeID > deserializeSHAMapNodeID(void const *data, std::size_t size)
Return an object representing a serialized SHAMap Node ID.
 
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
 
@ ValidatorListPropagation
 
@ ValidatorList2Propagation
 
std::string base64_decode(std::string_view data)
 
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
 
http_response_type makeResponse(bool crawlPublic, http_request_type const &req, beast::IP::Address public_ip, beast::IP::Address remote_ip, uint256 const &sharedValue, std::optional< std::uint32_t > networkID, ProtocolVersion protocol, Application &app)
Make http response.
 
static bool stringIsUint256Sized(std::string const &pBuffStr)
 
static constexpr char FEATURE_LEDGER_REPLAY[]
 
std::pair< std::size_t, boost::system::error_code > invokeProtocolMessage(Buffers const &buffers, Handler &handler, std::size_t &hint)
Calls the handler for up to one protocol message in the passed buffers.
 
std::optional< uint256 > makeSharedValue(stream_type &ssl, beast::Journal journal)
Computes a shared value based on the SSL connection state.
 
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
 
std::enable_if_t< std::is_integral< Integral >::value &&detail::is_engine< Engine >::value, Integral > rand_int(Engine &engine, Integral min, Integral max)
Return a uniformly distributed random integer.
 
std::string strHex(FwdIt begin, FwdIt end)
 
static std::shared_ptr< PeerImp > getPeerWithLedger(OverlayImpl &ov, uint256 const &ledgerHash, LedgerIndex ledger, PeerImp const *skip)
 
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
 
Stopwatch & stopwatch()
Returns an instance of a wall clock.
 
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
 
NodeID calcNodeID(PublicKey const &)
Calculate the 160-bit node ID from a node public key.
 
std::string getFingerprint(beast::IP::Endpoint const &address, std::optional< PublicKey > const &publicKey=std::nullopt, std::optional< std::string > const &id=std::nullopt)
 
static std::shared_ptr< PeerImp > getPeerWithTree(OverlayImpl &ov, uint256 const &rootHash, PeerImp const *skip)
 
bool peerFeatureEnabled(headers const &request, std::string const &feature, std::string value, bool config)
Check if a feature should be enabled for a peer.
 
void forceValidity(HashRouter &router, uint256 const &txid, Validity validity)
Sets the validity of a given transaction in the cache.
 
static constexpr char FEATURE_TXRR[]
 
std::string to_string(base_uint< Bits, Tag > const &a)
 
std::optional< Rules > const & getCurrentTransactionRules()
 
Number root(Number f, unsigned d)
 
@ proposal
proposal for signing
 
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
 
std::pair< Validity, std::string > checkValidity(HashRouter &router, STTx const &tx, Rules const &rules, Config const &config)
Checks transaction signature and local checks.
 
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
 
static constexpr char FEATURE_VPRR[]
 
constexpr std::uint32_t tfInnerBatchTxn
 
T shared_from_this(T... args)
 
beast::IP::Address public_ip
 
std::optional< std::uint32_t > networkID
 
bool peerPrivate
true if we want our IP address kept private.
 
void update(Resource::Charge f, std::string const &add)
 
Describes a single consumer.
 
beast::IP::Endpoint address
 
Data format for exchanging consumption information across peers.
 
std::vector< Item > items