20 #include <ripple/app/consensus/RCLValidations.h>
21 #include <ripple/app/ledger/InboundLedgers.h>
22 #include <ripple/app/ledger/InboundTransactions.h>
23 #include <ripple/app/ledger/LedgerMaster.h>
24 #include <ripple/app/ledger/TransactionMaster.h>
25 #include <ripple/app/misc/HashRouter.h>
26 #include <ripple/app/misc/LoadFeeTrack.h>
27 #include <ripple/app/misc/NetworkOPs.h>
28 #include <ripple/app/misc/Transaction.h>
29 #include <ripple/app/misc/ValidatorList.h>
30 #include <ripple/app/tx/apply.h>
31 #include <ripple/basics/SubmitSync.h>
32 #include <ripple/basics/UptimeClock.h>
33 #include <ripple/basics/base64.h>
34 #include <ripple/basics/random.h>
35 #include <ripple/basics/safe_cast.h>
36 #include <ripple/beast/clock/abstract_clock.h>
37 #include <ripple/beast/core/LexicalCast.h>
38 #include <ripple/beast/core/SemanticVersion.h>
39 #include <ripple/nodestore/DatabaseShard.h>
40 #include <ripple/overlay/Cluster.h>
41 #include <ripple/overlay/impl/PeerImp.h>
42 #include <ripple/overlay/impl/Tuning.h>
43 #include <ripple/overlay/predicates.h>
44 #include <ripple/protocol/Protocol.h>
45 #include <ripple/protocol/digest.h>
47 #include <boost/algorithm/string/predicate.hpp>
48 #include <boost/beast/core/ostream.hpp>
57 using namespace std::chrono_literals;
82 , sink_(app_.journal(
"Peer"), makePrefix(id))
83 , p_sink_(app_.journal(
"Protocol"), makePrefix(id))
86 , stream_ptr_(
std::move(stream_ptr))
87 , socket_(stream_ptr_->next_layer().socket())
88 , stream_(*stream_ptr_)
89 , strand_(socket_.get_executor())
91 , remote_address_(slot->remote_endpoint())
95 , tracking_(Tracking::unknown)
96 , trackingTime_(clock_type::now())
97 , publicKey_(publicKey)
98 , lastPingTime_(clock_type::now())
99 , creationTime_(clock_type::now())
100 , squelch_(app_.journal(
"Squelch"))
104 , request_(std::move(request))
106 , compressionEnabled_(
111 app_.config().COMPRESSION)
117 app_.config().TX_REDUCE_RELAY_ENABLE))
121 app_.config().VP_REDUCE_RELAY_ENABLE))
125 app_.config().LEDGER_REPLAY))
126 , ledgerReplayMsgHandler_(app, app.getLedgerReplayer())
128 JLOG(journal_.info()) <<
"compression enabled "
129 << (compressionEnabled_ == Compressed::On)
130 <<
" vp reduce-relay enabled "
131 << vpReduceRelayEnabled_
132 <<
" tx reduce-relay enabled "
133 << txReduceRelayEnabled_ <<
" on " << remote_address_
139 const bool inCluster{
cluster()};
162 if (!
strand_.running_in_this_thread())
165 auto parseLedgerHash =
179 if (
auto const iter =
headers_.find(
"Closed-Ledger");
182 closed = parseLedgerHash(iter->value());
185 fail(
"Malformed handshake data (1)");
188 if (
auto const iter =
headers_.find(
"Previous-Ledger");
191 previous = parseLedgerHash(iter->value());
194 fail(
"Malformed handshake data (2)");
197 if (previous && !closed)
198 fail(
"Malformed handshake data (3)");
220 if (!
strand_.running_in_this_thread())
246 if (!
strand_.running_in_this_thread())
253 auto validator = m->getValidatorKey();
254 if (validator && !
squelch_.expireSquelch(*validator))
258 safe_cast<TrafficCount::category>(m->getCategory()),
276 <<
" sendq: " << sendq_size;
284 boost::asio::async_write(
293 std::placeholders::_1,
294 std::placeholders::_2)));
300 if (!
strand_.running_in_this_thread())
306 protocol::TMHaveTransactions ht;
308 ht.add_hashes(hash.data(), hash.size());
312 send(std::make_shared<Message>(ht, protocol::mtHAVE_TRANSACTIONS));
319 if (!
strand_.running_in_this_thread())
336 if (!
strand_.running_in_this_thread())
341 auto removed =
txQueue_.erase(hash);
353 fail(
"charge: Resources");
362 auto const iter =
headers_.find(
"Crawl");
365 return boost::iequals(iter->value(),
"public");
391 ret[jss::inbound] =
true;
395 ret[jss::cluster] =
true;
403 ret[jss::server_domain] =
domain();
405 if (
auto const nid =
headers_[
"Network-ID"]; !nid.empty())
411 ret[jss::version] = version;
422 std::chrono::duration_cast<std::chrono::seconds>(
uptime()).count());
427 if ((minSeq != 0) || (maxSeq != 0))
428 ret[jss::complete_ledgers] =
434 ret[jss::track] =
"diverged";
438 ret[jss::track] =
"unknown";
447 protocol::TMStatusChange last_status;
454 if (closedLedgerHash != beast::zero)
455 ret[jss::ledger] =
to_string(closedLedgerHash);
457 if (last_status.has_newstatus())
459 switch (last_status.newstatus())
461 case protocol::nsCONNECTING:
462 ret[jss::status] =
"connecting";
465 case protocol::nsCONNECTED:
466 ret[jss::status] =
"connected";
469 case protocol::nsMONITORING:
470 ret[jss::status] =
"monitoring";
473 case protocol::nsVALIDATING:
474 ret[jss::status] =
"validating";
477 case protocol::nsSHUTTING:
478 ret[jss::status] =
"shutting";
483 <<
"Unknown status: " << last_status.newstatus();
488 ret[jss::metrics][jss::total_bytes_recv] =
490 ret[jss::metrics][jss::total_bytes_sent] =
492 ret[jss::metrics][jss::avg_bps_recv] =
494 ret[jss::metrics][jss::avg_bps_sent] =
537 return boost::icl::contains(it->second.finalized(), shardIndex);
583 assert(
strand_.running_in_this_thread());
605 if (!
strand_.running_in_this_thread())
616 <<
" failed: " << reason;
624 assert(
strand_.running_in_this_thread());
644 assert(
strand_.running_in_this_thread());
651 stream_.async_shutdown(bind_executor(
661 timer_.expires_from_now(peerTimerInterval, ec);
668 timer_.async_wait(bind_executor(
698 if (ec == boost::asio::error::operation_aborted)
710 fail(
"Large send queue");
716 clock_type::duration duration;
737 fail(
"Ping Timeout");
744 protocol::TMPing message;
745 message.set_type(protocol::TMPing::ptPING);
748 send(std::make_shared<Message>(message, protocol::mtPING));
760 JLOG(
journal_.
error()) <<
"onShutdown: expected error condition";
763 if (ec != boost::asio::error::eof)
764 return fail(
"onShutdown", ec);
781 return fail(
"makeSharedValue: Unexpected failure");
802 auto write_buffer = std::make_shared<boost::beast::multi_buffer>();
815 boost::asio::async_write(
817 write_buffer->data(),
818 boost::asio::transfer_all(),
825 if (ec == boost::asio::error::operation_aborted)
828 return fail(
"onWriteResponse", ec);
829 if (write_buffer->size() == bytes_transferred)
831 return fail(
"Failed to write header");
887 protocol::TMGetPeerShardInfoV2 tmGPS;
889 send(std::make_shared<Message>(tmGPS, protocol::mtGET_PEER_SHARD_INFO_V2));
900 if (ec == boost::asio::error::operation_aborted)
902 if (ec == boost::asio::error::eof)
908 return fail(
"onReadMessage", ec);
911 if (bytes_transferred > 0)
912 stream <<
"onReadMessage: " << bytes_transferred <<
" bytes";
914 stream <<
"onReadMessage";
917 metrics_.recv.add_message(bytes_transferred);
929 return fail(
"onReadMessage", ec);
934 if (bytes_consumed == 0)
947 std::placeholders::_1,
948 std::placeholders::_2)));
956 if (ec == boost::asio::error::operation_aborted)
959 return fail(
"onWriteMessage", ec);
962 if (bytes_transferred > 0)
963 stream <<
"onWriteMessage: " << bytes_transferred <<
" bytes";
965 stream <<
"onWriteMessage";
968 metrics_.sent.add_message(bytes_transferred);
975 return boost::asio::async_write(
984 std::placeholders::_1,
985 std::placeholders::_2)));
990 return stream_.async_shutdown(bind_executor(
995 std::placeholders::_1)));
1025 if ((type == MessageType::mtTRANSACTION ||
1026 type == MessageType::mtHAVE_TRANSACTIONS ||
1027 type == MessageType::mtTRANSACTIONS ||
1029 category == TrafficCount::category::get_transactions ||
1031 category == TrafficCount::category::ld_tsc_get ||
1032 category == TrafficCount::category::ld_tsc_share ||
1034 category == TrafficCount::category::gl_tsc_share ||
1035 category == TrafficCount::category::gl_tsc_get) &&
1039 static_cast<MessageType
>(type),
static_cast<std::uint64_t>(size));
1041 JLOG(
journal_.
trace()) <<
"onMessageBegin: " << type <<
" " << size <<
" "
1042 << uncompressed_size <<
" " << isCompressed;
1057 auto const s = m->list_size();
1077 if (m->type() == protocol::TMPing::ptPING)
1081 m->set_type(protocol::TMPing::ptPONG);
1082 send(std::make_shared<Message>(*m, protocol::mtPING));
1086 if (m->type() == protocol::TMPing::ptPONG && m->has_seq())
1096 auto const rtt = std::chrono::round<std::chrono::milliseconds>(
1121 for (
int i = 0; i < m->clusternodes().size(); ++i)
1123 protocol::TMClusterNode
const& node = m->clusternodes(i);
1126 if (node.has_nodename())
1127 name = node.nodename();
1129 auto const publicKey =
1136 auto const reportTime =
1140 *publicKey,
name, node.nodeload(), reportTime);
1144 int loadSources = m->loadsources().size();
1145 if (loadSources != 0)
1148 gossip.
items.reserve(loadSources);
1149 for (
int i = 0; i < m->loadsources().size(); ++i)
1151 protocol::TMLoadSource
const& node = m->loadsources(i);
1156 gossip.
items.push_back(item);
1169 if (status.getReportTime() >= thresh)
1170 fees.push_back(status.getLoadFee());
1175 auto const index = fees.size() / 2;
1177 clusterFee = fees[index];
1205 return badData(
"Invalid relays");
1214 auto const peerChainSz{m->peerchain_size()};
1215 if (peerChainSz > 0)
1218 return badData(
"Invalid peer chain size");
1221 return badData(
"Invalid relays and peer chain size");
1223 for (
int i = 0; i < peerChainSz; ++i)
1225 auto const slice{
makeSlice(m->peerchain(i).publickey())};
1229 return badData(
"Invalid peer public key");
1232 if (!pubKeyChain.
emplace(slice).second)
1233 return badData(
"Invalid peer public key");
1240 auto reply{shardStore->getShardInfo()->makeMessage(
app_)};
1241 if (peerChainSz > 0)
1242 *(reply.mutable_peerchain()) = m->peerchain();
1243 send(std::make_shared<Message>(reply, protocol::mtPEER_SHARD_INFO_V2));
1246 if (m->relays() == 0)
1250 if (peerChainSz == 0)
1257 m->set_relays(m->relays() - 1);
1259 std::make_shared<Message>(*m, protocol::mtGET_PEER_SHARD_INFO_V2),
1261 return pubKeyChain.
find(peer->getNodePublic()) != pubKeyChain.
end();
1273 if (curLedgerSeq >= db.earliestLedgerSeq())
1274 return db.seqToShardIndex(curLedgerSeq);
1275 return std::nullopt;
1290 auto const timestamp{
1293 if (timestamp > (now + 5s))
1294 return badData(
"Invalid timestamp");
1297 using namespace std::chrono_literals;
1298 if (timestamp < (now - 5min))
1299 return badData(
"Stale timestamp");
1301 s.
add32(m->timestamp());
1306 auto const numIncomplete{m->incomplete_size()};
1307 if (numIncomplete > 0)
1309 if (latestShardIndex && numIncomplete > *latestShardIndex)
1310 return badData(
"Invalid number of incomplete shards");
1313 for (
int i = 0; i < numIncomplete; ++i)
1315 auto const& incomplete{m->incomplete(i)};
1316 auto const shardIndex{incomplete.shardindex()};
1319 if (shardIndex < earliestShardIndex ||
1320 (latestShardIndex && shardIndex > latestShardIndex))
1322 return badData(
"Invalid incomplete shard index");
1324 s.
add32(shardIndex);
1327 auto const state{
static_cast<ShardState>(incomplete.state())};
1339 return badData(
"Invalid incomplete shard state");
1341 s.
add32(incomplete.state());
1345 if (incomplete.has_progress())
1347 progress = incomplete.progress();
1348 if (progress < 1 || progress > 100)
1349 return badData(
"Invalid incomplete shard progress");
1354 if (!
shardInfo.update(shardIndex, state, progress))
1355 return badData(
"Invalid duplicate incomplete shards");
1360 if (m->has_finalized())
1362 auto const& str{m->finalized()};
1364 return badData(
"Invalid finalized shards");
1366 if (!
shardInfo.setFinalizedFromString(str))
1367 return badData(
"Invalid finalized shard indexes");
1370 auto const numFinalized{boost::icl::length(
finalized)};
1371 if (numFinalized == 0 ||
1372 boost::icl::first(
finalized) < earliestShardIndex ||
1373 (latestShardIndex &&
1374 boost::icl::last(
finalized) > latestShardIndex))
1376 return badData(
"Invalid finalized shard indexes");
1379 if (latestShardIndex &&
1380 (numFinalized + numIncomplete) > *latestShardIndex)
1382 return badData(
"Invalid number of finalized and incomplete shards");
1385 s.
addRaw(str.data(), str.size());
1391 return badData(
"Invalid public key");
1396 return badData(
"Invalid public key");
1400 return badData(
"Invalid signature");
1403 auto const peerChainSz{m->peerchain_size()};
1404 if (peerChainSz > 0)
1408 return badData(
"Invalid peer chain size");
1416 for (
int i = 0; i < peerChainSz; ++i)
1419 slice =
makeSlice(m->peerchain(i).publickey());
1421 return badData(
"Invalid peer public key");
1424 if (!pubKeyChain.
emplace(slice).second)
1425 return badData(
"Invalid peer public key");
1430 makeSlice(m->peerchain(peerChainSz - 1).publickey()));
1433 m->mutable_peerchain()->RemoveLast();
1435 std::make_shared<Message>(*m, protocol::mtPEER_SHARD_INFO_V2));
1437 <<
"Relayed TMPeerShardInfoV2 from peer IP "
1439 << peer->getRemoteAddress().to_string();
1449 <<
"Consumed TMPeerShardInfoV2 originating from public key "
1452 << (
shardInfo.incomplete().empty() ?
"empty"
1462 else if (
shardInfo.msgTimestamp() > it->second.msgTimestamp())
1467 if (peerChainSz == 0)
1481 if (m->endpoints_v2().size() >= 1024)
1488 endpoints.
reserve(m->endpoints_v2().size());
1490 for (
auto const& tm : m->endpoints_v2())
1497 << tm.endpoint() <<
"}";
1514 if (!endpoints.
empty())
1537 <<
"Need network ledger";
1545 auto stx = std::make_shared<STTx const>(sit);
1546 uint256 txID = stx->getTransactionID();
1570 bool checkSignature =
true;
1573 if (!m->has_deferred() || !m->deferred())
1577 flags |= SF_TRUSTED;
1584 checkSignature =
false;
1591 <<
"No new transactions until synchronized";
1604 "recvTransaction->checkTransaction",
1609 if (
auto peer = weak.lock())
1610 peer->checkTransaction(flags, checkSignature, stx);
1617 <<
"Transaction invalid: " <<
strHex(m->rawtransaction())
1618 <<
". Exception: " << ex.
what();
1629 auto const itype{m->itype()};
1632 if (itype < protocol::liBASE || itype > protocol::liTS_CANDIDATE)
1633 return badData(
"Invalid ledger info type");
1638 return std::nullopt;
1641 if (itype == protocol::liTS_CANDIDATE)
1643 if (!m->has_ledgerhash())
1644 return badData(
"Invalid TX candidate set, missing TX set hash");
1647 !m->has_ledgerhash() && !m->has_ledgerseq() &&
1648 !(ltype && *ltype == protocol::ltCLOSED))
1650 return badData(
"Invalid request");
1654 if (ltype && (*ltype < protocol::ltACCEPTED || *ltype > protocol::ltCLOSED))
1655 return badData(
"Invalid ledger type");
1659 return badData(
"Invalid ledger hash");
1662 if (m->has_ledgerseq())
1664 auto const ledgerSeq{m->ledgerseq()};
1674 using namespace std::chrono_literals;
1684 if (itype != protocol::liBASE)
1686 if (m->nodeids_size() <= 0)
1687 return badData(
"Invalid ledger node IDs");
1689 for (
auto const& nodeId : m->nodeids())
1692 return badData(
"Invalid SHAMap node ID");
1697 if (m->has_querytype() && m->querytype() != protocol::qtINDIRECT)
1698 return badData(
"Invalid query type");
1701 if (m->has_querydepth())
1704 itype == protocol::liBASE)
1706 return badData(
"Invalid query depth");
1713 if (
auto peer = weak.
lock())
1714 peer->processLedgerRequest(m);
1732 if (
auto peer = weak.
lock())
1735 peer->ledgerReplayMsgHandler_.processProofPathRequest(m);
1736 if (reply.has_error())
1738 if (reply.error() == protocol::TMReplyError::reBAD_REQUEST)
1739 peer->charge(Resource::feeInvalidRequest);
1741 peer->charge(Resource::feeRequestNoReply);
1745 peer->send(std::make_shared<Message>(
1746 reply, protocol::mtPROOF_PATH_RESPONSE));
1781 if (
auto peer = weak.
lock())
1784 peer->ledgerReplayMsgHandler_.processReplayDeltaRequest(m);
1785 if (reply.has_error())
1787 if (reply.error() == protocol::TMReplyError::reBAD_REQUEST)
1788 peer->charge(Resource::feeInvalidRequest);
1790 peer->charge(Resource::feeRequestNoReply);
1794 peer->send(std::make_shared<Message>(
1795 reply, protocol::mtREPLAY_DELTA_RESPONSE));
1826 return badData(
"Invalid ledger hash");
1830 auto const ledgerSeq{m->ledgerseq()};
1831 if (m->type() == protocol::liTS_CANDIDATE)
1850 using namespace std::chrono_literals;
1861 if (m->type() < protocol::liBASE || m->type() > protocol::liTS_CANDIDATE)
1862 return badData(
"Invalid ledger info type");
1865 if (m->has_error() &&
1866 (m->error() < protocol::reNO_LEDGER ||
1867 m->error() > protocol::reBAD_REQUEST))
1869 return badData(
"Invalid reply error");
1876 "Invalid Ledger/TXset nodes " +
std::to_string(m->nodes_size()));
1880 if (m->has_requestcookie())
1884 m->clear_requestcookie();
1885 peer->send(std::make_shared<Message>(*m, protocol::mtLEDGER_DATA));
1889 JLOG(
p_journal_.
info()) <<
"Unable to route TX/ledger data reply";
1894 uint256 const ledgerHash{m->ledgerhash()};
1897 if (m->type() == protocol::liTS_CANDIDATE)
1901 jtTXN_DATA,
"recvPeerData", [weak, ledgerHash, m]() {
1902 if (
auto peer = weak.lock())
1904 peer->app_.getInboundTransactions().gotData(
1905 ledgerHash, peer, m);
1918 protocol::TMProposeSet&
set = *m;
1924 if ((std::clamp<std::size_t>(sig.size(), 64, 72) != sig.size()) ||
1952 uint256 const proposeHash{
set.currenttxhash()};
1953 uint256 const prevLedger{
set.previousledger()};
1965 if (
auto [added, relayed] =
1974 suppression, publicKey,
id_, protocol::mtPROPOSE_LEDGER);
1984 <<
"Proposal: Dropping untrusted (peer divergence)";
1996 <<
"Proposal: " << (isTrusted ?
"trusted" :
"untrusted");
1999 if (
set.has_ledgerseq())
2000 ledgerSeq =
set.ledgerseq();
2014 beast::get_abstract_clock<std::chrono::steady_clock>()});
2019 "recvPropose->checkPropose",
2021 if (
auto peer = weak.lock())
2022 peer->checkPropose(isTrusted, m,
proposal);
2031 if (!m->has_networktime())
2036 if (!
last_status_.has_newstatus() || m->has_newstatus())
2041 protocol::NodeStatus status =
last_status_.newstatus();
2043 m->set_newstatus(status);
2047 if (m->newevent() == protocol::neLOST_SYNC)
2049 bool outOfSync{
false};
2070 bool const peerChangedLedgers{
2077 if (peerChangedLedgers)
2088 if (m->has_ledgerhashprevious() &&
2099 if (peerChangedLedgers)
2109 if (m->has_firstseq() && m->has_lastseq())
2120 if (m->has_ledgerseq() &&
2130 if (m->has_newstatus())
2132 switch (m->newstatus())
2134 case protocol::nsCONNECTING:
2135 j[jss::status] =
"CONNECTING";
2137 case protocol::nsCONNECTED:
2138 j[jss::status] =
"CONNECTED";
2140 case protocol::nsMONITORING:
2141 j[jss::status] =
"MONITORING";
2143 case protocol::nsVALIDATING:
2144 j[jss::status] =
"VALIDATING";
2146 case protocol::nsSHUTTING:
2147 j[jss::status] =
"SHUTTING";
2152 if (m->has_newevent())
2154 switch (m->newevent())
2156 case protocol::neCLOSING_LEDGER:
2157 j[jss::action] =
"CLOSING_LEDGER";
2159 case protocol::neACCEPTED_LEDGER:
2160 j[jss::action] =
"ACCEPTED_LEDGER";
2162 case protocol::neSWITCHED_LEDGER:
2163 j[jss::action] =
"SWITCHED_LEDGER";
2165 case protocol::neLOST_SYNC:
2166 j[jss::action] =
"LOST_SYNC";
2171 if (m->has_ledgerseq())
2173 j[jss::ledger_index] = m->ledgerseq();
2176 if (m->has_ledgerhash())
2178 uint256 closedLedgerHash{};
2180 std::lock_guard sl(recentLock_);
2181 closedLedgerHash = closedLedgerHash_;
2183 j[jss::ledger_hash] =
to_string(closedLedgerHash);
2186 if (m->has_networktime())
2188 j[jss::date] = Json::UInt(m->networktime());
2191 if (m->has_firstseq() && m->has_lastseq())
2193 j[jss::ledger_index_min] = Json::UInt(m->firstseq());
2194 j[jss::ledger_index_max] = Json::UInt(m->lastseq());
2210 serverSeq = maxLedger_;
2216 checkTracking(serverSeq, validationSeq);
2225 if (diff < Tuning::convergedLedgerLimit)
2228 tracking_ = Tracking::converged;
2231 if ((diff > Tuning::divergedLedgerLimit) &&
2232 (tracking_.load() != Tracking::diverged))
2237 tracking_ = Tracking::diverged;
2238 trackingTime_ = clock_type::now();
2247 fee_ = Resource::feeInvalidRequest;
2251 uint256 const hash{m->hash()};
2253 if (m->status() == protocol::tsHAVE)
2257 if (
std::find(recentTxSets_.begin(), recentTxSets_.end(), hash) !=
2258 recentTxSets_.end())
2260 fee_ = Resource::feeUnwantedData;
2264 recentTxSets_.push_back(hash);
2269 PeerImp::onValidatorListMessage(
2279 JLOG(p_journal_.warn()) <<
"Ignored malformed " << messageType
2280 <<
" from peer " << remote_address_;
2282 fee_ = Resource::feeHighBurdenPeer;
2288 JLOG(p_journal_.debug())
2289 <<
"Received " << messageType <<
" from " << remote_address_.to_string()
2290 <<
" (" << id_ <<
")";
2292 if (!app_.getHashRouter().addSuppressionPeer(hash, id_))
2294 JLOG(p_journal_.debug())
2295 << messageType <<
": received duplicate " << messageType;
2299 fee_ = Resource::feeUnwantedData;
2303 auto const applyResult = app_.validators().applyListsAndBroadcast(
2307 remote_address_.to_string(),
2310 app_.getHashRouter(),
2313 JLOG(p_journal_.debug())
2314 <<
"Processed " << messageType <<
" version " << version <<
" from "
2315 << (applyResult.publisherKey ?
strHex(*applyResult.publisherKey)
2316 :
"unknown or invalid publisher")
2317 <<
" from " << remote_address_.to_string() <<
" (" << id_
2318 <<
") with best result " << to_string(applyResult.bestDisposition());
2321 switch (applyResult.bestDisposition())
2324 case ListDisposition::accepted:
2326 case ListDisposition::expired:
2328 case ListDisposition::pending: {
2331 assert(applyResult.publisherKey);
2332 auto const& pubKey = *applyResult.publisherKey;
2334 if (
auto const iter = publisherListSequences_.find(pubKey);
2335 iter != publisherListSequences_.end())
2337 assert(iter->second < applyResult.sequence);
2340 publisherListSequences_[pubKey] = applyResult.sequence;
2343 case ListDisposition::same_sequence:
2344 case ListDisposition::known_sequence:
2348 assert(applyResult.sequence && applyResult.publisherKey);
2350 publisherListSequences_[*applyResult.publisherKey] <=
2351 applyResult.sequence);
2356 case ListDisposition::stale:
2357 case ListDisposition::untrusted:
2358 case ListDisposition::invalid:
2359 case ListDisposition::unsupported_version:
2366 switch (applyResult.worstDisposition())
2368 case ListDisposition::accepted:
2369 case ListDisposition::expired:
2370 case ListDisposition::pending:
2373 case ListDisposition::same_sequence:
2374 case ListDisposition::known_sequence:
2378 fee_ = Resource::feeUnwantedData;
2380 case ListDisposition::stale:
2383 fee_ = Resource::feeBadData;
2385 case ListDisposition::untrusted:
2389 fee_ = Resource::feeUnwantedData;
2391 case ListDisposition::invalid:
2393 fee_ = Resource::feeInvalidSignature;
2395 case ListDisposition::unsupported_version:
2398 fee_ = Resource::feeBadData;
2405 for (
auto const& [disp, count] : applyResult.dispositions)
2410 case ListDisposition::accepted:
2411 JLOG(p_journal_.debug())
2412 <<
"Applied " << count <<
" new " << messageType
2413 <<
"(s) from peer " << remote_address_;
2416 case ListDisposition::expired:
2417 JLOG(p_journal_.debug())
2418 <<
"Applied " << count <<
" expired " << messageType
2419 <<
"(s) from peer " << remote_address_;
2422 case ListDisposition::pending:
2423 JLOG(p_journal_.debug())
2424 <<
"Processed " << count <<
" future " << messageType
2425 <<
"(s) from peer " << remote_address_;
2427 case ListDisposition::same_sequence:
2428 JLOG(p_journal_.warn())
2429 <<
"Ignored " << count <<
" " << messageType
2430 <<
"(s) with current sequence from peer "
2433 case ListDisposition::known_sequence:
2434 JLOG(p_journal_.warn())
2435 <<
"Ignored " << count <<
" " << messageType
2436 <<
"(s) with future sequence from peer " << remote_address_;
2438 case ListDisposition::stale:
2439 JLOG(p_journal_.warn())
2440 <<
"Ignored " << count <<
"stale " << messageType
2441 <<
"(s) from peer " << remote_address_;
2443 case ListDisposition::untrusted:
2444 JLOG(p_journal_.warn())
2445 <<
"Ignored " << count <<
" untrusted " << messageType
2446 <<
"(s) from peer " << remote_address_;
2448 case ListDisposition::unsupported_version:
2449 JLOG(p_journal_.warn())
2450 <<
"Ignored " << count <<
"unsupported version "
2451 << messageType <<
"(s) from peer " << remote_address_;
2453 case ListDisposition::invalid:
2454 JLOG(p_journal_.warn())
2455 <<
"Ignored " << count <<
"invalid " << messageType
2456 <<
"(s) from peer " << remote_address_;
2469 if (!supportsFeature(ProtocolFeature::ValidatorListPropagation))
2471 JLOG(p_journal_.debug())
2472 <<
"ValidatorList: received validator list from peer using "
2473 <<
"protocol version " << to_string(protocol_)
2474 <<
" which shouldn't support this feature.";
2475 fee_ = Resource::feeUnwantedData;
2478 onValidatorListMessage(
2482 ValidatorList::parseBlobs(*m));
2486 JLOG(p_journal_.warn()) <<
"ValidatorList: Exception, " << e.
what()
2487 <<
" from peer " << remote_address_;
2488 fee_ = Resource::feeBadData;
2498 if (!supportsFeature(ProtocolFeature::ValidatorList2Propagation))
2500 JLOG(p_journal_.debug())
2501 <<
"ValidatorListCollection: received validator list from peer "
2502 <<
"using protocol version " << to_string(protocol_)
2503 <<
" which shouldn't support this feature.";
2504 fee_ = Resource::feeUnwantedData;
2507 else if (m->version() < 2)
2509 JLOG(p_journal_.debug())
2510 <<
"ValidatorListCollection: received invalid validator list "
2512 << m->version() <<
" from peer using protocol version "
2513 << to_string(protocol_);
2514 fee_ = Resource::feeBadData;
2517 onValidatorListMessage(
2518 "ValidatorListCollection",
2521 ValidatorList::parseBlobs(*m));
2525 JLOG(p_journal_.warn()) <<
"ValidatorListCollection: Exception, "
2526 << e.
what() <<
" from peer " << remote_address_;
2527 fee_ = Resource::feeBadData;
2534 if (m->validation().size() < 50)
2536 JLOG(p_journal_.warn()) <<
"Validation: Too small";
2537 fee_ = Resource::feeInvalidRequest;
2543 auto const closeTime = app_.timeKeeper().closeTime();
2548 val = std::make_shared<STValidation>(
2552 app_.validatorManifests().getMasterKey(pk));
2555 val->setSeen(closeTime);
2559 app_.getValidations().parms(),
2560 app_.timeKeeper().closeTime(),
2562 val->getSeenTime()))
2564 JLOG(p_journal_.trace()) <<
"Validation: Not current";
2565 fee_ = Resource::feeUnwantedData;
2572 auto const isTrusted =
2573 app_.validators().trusted(val->getSignerPublic());
2578 if (!isTrusted && app_.config().RELAY_UNTRUSTED_VALIDATIONS == -1)
2583 if (
auto [added, relayed] =
2584 app_.getHashRouter().addSuppressionPeerWithStatus(key, id_);
2591 if (reduceRelayReady() && relayed &&
2592 (
stopwatch().now() - *relayed) < reduce_relay::IDLED)
2593 overlay_.updateSlotAndSquelch(
2594 key, val->getSignerPublic(), id_, protocol::mtVALIDATION);
2595 JLOG(p_journal_.trace()) <<
"Validation: duplicate";
2599 if (!isTrusted && (tracking_.load() == Tracking::diverged))
2601 JLOG(p_journal_.debug())
2602 <<
"Dropping untrusted validation from diverged peer";
2604 else if (isTrusted || !app_.getFeeTrack().isLoadedLocal())
2608 isTrusted ?
"Trusted validation" :
"Untrusted validation";
2613 to_string(val->getNodeID());
2620 app_.getJobQueue().addJob(
2623 [weak, val, m, key]() {
2624 if (
auto peer = weak.
lock())
2625 peer->checkValidation(val, key, m);
2630 JLOG(p_journal_.debug())
2631 <<
"Dropping untrusted validation for load";
2636 JLOG(p_journal_.warn())
2637 <<
"Exception processing validation: " << e.
what();
2638 fee_ = Resource::feeInvalidRequest;
2645 protocol::TMGetObjectByHash& packet = *m;
2647 JLOG(p_journal_.trace()) <<
"received TMGetObjectByHash " << packet.type()
2648 <<
" " << packet.objects_size();
2653 if (send_queue_.size() >= Tuning::dropSendQueue)
2655 JLOG(p_journal_.debug()) <<
"GetObject: Large send queue";
2659 if (packet.type() == protocol::TMGetObjectByHash::otFETCH_PACK)
2665 if (packet.type() == protocol::TMGetObjectByHash::otTRANSACTIONS)
2667 if (!txReduceRelayEnabled())
2669 JLOG(p_journal_.error())
2670 <<
"TMGetObjectByHash: tx reduce-relay is disabled";
2671 fee_ = Resource::feeInvalidRequest;
2676 app_.getJobQueue().addJob(
2678 if (
auto peer = weak.
lock())
2679 peer->doTransactions(m);
2684 fee_ = Resource::feeMediumBurdenPeer;
2686 protocol::TMGetObjectByHash reply;
2688 reply.set_query(
false);
2690 if (packet.has_seq())
2691 reply.set_seq(packet.seq());
2693 reply.set_type(packet.type());
2695 if (packet.has_ledgerhash())
2699 fee_ = Resource::feeInvalidRequest;
2703 reply.set_ledgerhash(packet.ledgerhash());
2707 for (
int i = 0; i < packet.objects_size(); ++i)
2709 auto const& obj = packet.objects(i);
2712 uint256 const hash{obj.hash()};
2715 std::uint32_t seq{obj.has_ledgerseq() ? obj.ledgerseq() : 0};
2716 auto nodeObject{app_.getNodeStore().fetchNodeObject(hash, seq)};
2719 if (
auto shardStore = app_.getShardStore())
2721 if (seq >= shardStore->earliestLedgerSeq())
2722 nodeObject = shardStore->fetchNodeObject(hash, seq);
2727 protocol::TMIndexedObject& newObj = *reply.add_objects();
2728 newObj.set_hash(hash.begin(), hash.size());
2730 &nodeObject->getData().front(),
2731 nodeObject->getData().size());
2733 if (obj.has_nodeid())
2734 newObj.set_index(obj.nodeid());
2735 if (obj.has_ledgerseq())
2736 newObj.set_ledgerseq(obj.ledgerseq());
2743 JLOG(p_journal_.trace()) <<
"GetObj: " << reply.objects_size() <<
" of "
2744 << packet.objects_size();
2745 send(std::make_shared<Message>(reply, protocol::mtGET_OBJECTS));
2752 bool progress =
false;
2754 for (
int i = 0; i < packet.objects_size(); ++i)
2756 const protocol::TMIndexedObject& obj = packet.objects(i);
2760 if (obj.has_ledgerseq())
2762 if (obj.ledgerseq() != pLSeq)
2764 if (pLDo && (pLSeq != 0))
2766 JLOG(p_journal_.debug())
2767 <<
"GetObj: Full fetch pack for " << pLSeq;
2769 pLSeq = obj.ledgerseq();
2770 pLDo = !app_.getLedgerMaster().haveLedger(pLSeq);
2774 JLOG(p_journal_.debug())
2775 <<
"GetObj: Late fetch pack for " << pLSeq;
2784 uint256 const hash{obj.hash()};
2786 app_.getLedgerMaster().addFetchPack(
2788 std::make_shared<Blob>(
2789 obj.data().begin(), obj.data().end()));
2794 if (pLDo && (pLSeq != 0))
2796 JLOG(p_journal_.debug())
2797 <<
"GetObj: Partial fetch pack for " << pLSeq;
2799 if (packet.type() == protocol::TMGetObjectByHash::otFETCH_PACK)
2800 app_.getLedgerMaster().gotFetchPack(progress, pLSeq);
2807 if (!txReduceRelayEnabled())
2809 JLOG(p_journal_.error())
2810 <<
"TMHaveTransactions: tx reduce-relay is disabled";
2811 fee_ = Resource::feeInvalidRequest;
2816 app_.getJobQueue().addJob(
2818 if (
auto peer = weak.
lock())
2819 peer->handleHaveTransactions(m);
2824 PeerImp::handleHaveTransactions(
2827 protocol::TMGetObjectByHash tmBH;
2828 tmBH.set_type(protocol::TMGetObjectByHash_ObjectType_otTRANSACTIONS);
2829 tmBH.set_query(
true);
2831 JLOG(p_journal_.trace())
2832 <<
"received TMHaveTransactions " << m->hashes_size();
2838 JLOG(p_journal_.error())
2839 <<
"TMHaveTransactions with invalid hash size";
2840 fee_ = Resource::feeInvalidRequest;
2846 auto txn = app_.getMasterTransaction().fetch_from_cache(hash);
2848 JLOG(p_journal_.trace()) <<
"checking transaction " << (bool)txn;
2852 JLOG(p_journal_.debug()) <<
"adding transaction to request";
2854 auto obj = tmBH.add_objects();
2855 obj->set_hash(hash.
data(), hash.
size());
2862 removeTxQueue(hash);
2866 JLOG(p_journal_.trace())
2867 <<
"transaction request object is " << tmBH.objects_size();
2869 if (tmBH.objects_size() > 0)
2870 send(std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS));
2876 if (!txReduceRelayEnabled())
2878 JLOG(p_journal_.error())
2879 <<
"TMTransactions: tx reduce-relay is disabled";
2880 fee_ = Resource::feeInvalidRequest;
2884 JLOG(p_journal_.trace())
2885 <<
"received TMTransactions " << m->transactions_size();
2887 overlay_.addTxMetrics(m->transactions_size());
2892 m->mutable_transactions(i), [](protocol::TMTransaction*) {}),
2899 using on_message_fn =
2901 if (!strand_.running_in_this_thread())
2905 (on_message_fn)&PeerImp::onMessage, shared_from_this(), m));
2907 if (!m->has_validatorpubkey())
2909 charge(Resource::feeBadData);
2912 auto validator = m->validatorpubkey();
2916 charge(Resource::feeBadData);
2922 if (!app_.validators().listed(key))
2924 charge(Resource::feeBadData);
2925 JLOG(p_journal_.debug())
2926 <<
"onMessage: TMSquelch discarding non-validator squelch "
2932 if (key == app_.getValidationPublicKey())
2934 JLOG(p_journal_.debug())
2935 <<
"onMessage: TMSquelch discarding validator's squelch " << slice;
2940 m->has_squelchduration() ? m->squelchduration() : 0;
2942 squelch_.removeSquelch(key);
2944 charge(Resource::feeBadData);
2946 JLOG(p_journal_.debug())
2947 <<
"onMessage: TMSquelch " << slice <<
" " << id() <<
" " << duration;
2959 (void)lockedRecentLock;
2961 if (
std::find(recentLedgers_.begin(), recentLedgers_.end(), hash) !=
2962 recentLedgers_.end())
2965 recentLedgers_.push_back(hash);
2974 if (app_.getFeeTrack().isLoadedLocal() ||
2975 (app_.getLedgerMaster().getValidatedLedgerAge() > 40s) ||
2976 (app_.getJobQueue().getJobCount(
jtPACK) > 10))
2978 JLOG(p_journal_.info()) <<
"Too busy to make fetch pack";
2984 JLOG(p_journal_.warn()) <<
"FetchPack hash size malformed";
2985 fee_ = Resource::feeInvalidRequest;
2989 fee_ = Resource::feeHighBurdenPeer;
2991 uint256 const hash{packet->ledgerhash()};
2994 auto elapsed = UptimeClock::now();
2995 auto const pap = &app_;
2996 app_.getJobQueue().addJob(
2997 jtPACK,
"MakeFetchPack", [pap, weak, packet, hash, elapsed]() {
2998 pap->getLedgerMaster().makeFetchPack(weak, packet, hash, elapsed);
3003 PeerImp::doTransactions(
3006 protocol::TMTransactions reply;
3008 JLOG(p_journal_.trace()) <<
"received TMGetObjectByHash requesting tx "
3009 << packet->objects_size();
3011 if (packet->objects_size() > reduce_relay::MAX_TX_QUEUE_SIZE)
3013 JLOG(p_journal_.error()) <<
"doTransactions, invalid number of hashes";
3014 fee_ = Resource::feeInvalidRequest;
3020 auto const& obj = packet->objects(i);
3024 fee_ = Resource::feeInvalidRequest;
3030 auto txn = app_.getMasterTransaction().fetch_from_cache(hash);
3034 JLOG(p_journal_.error()) <<
"doTransactions, transaction not found "
3036 fee_ = Resource::feeInvalidRequest;
3041 auto tx = reply.add_transactions();
3042 auto sttx = txn->getSTransaction();
3044 tx->set_rawtransaction(s.
data(), s.
size());
3046 txn->getStatus() ==
INCLUDED ? protocol::tsCURRENT
3048 tx->set_receivetimestamp(
3049 app_.timeKeeper().now().time_since_epoch().count());
3050 tx->set_deferred(txn->getSubmitResult().queued);
3053 if (reply.transactions_size() > 0)
3054 send(std::make_shared<Message>(reply, protocol::mtTRANSACTIONS));
3058 PeerImp::checkTransaction(
3060 bool checkSignature,
3069 app_.getLedgerMaster().getValidLedgerIndex()))
3071 app_.getHashRouter().setFlags(stx->getTransactionID(), SF_BAD);
3072 charge(Resource::feeUnwantedData);
3080 app_.getHashRouter(),
3082 app_.getLedgerMaster().getValidatedRules(),
3084 valid != Validity::Valid)
3086 if (!validReason.empty())
3088 JLOG(p_journal_.trace())
3089 <<
"Exception checking transaction: " << validReason;
3093 app_.getHashRouter().setFlags(stx->getTransactionID(), SF_BAD);
3094 charge(Resource::feeInvalidSignature);
3101 app_.getHashRouter(), stx->getTransactionID(), Validity::Valid);
3105 auto tx = std::make_shared<Transaction>(stx, reason, app_);
3107 if (tx->getStatus() ==
INVALID)
3109 if (!reason.
empty())
3111 JLOG(p_journal_.trace())
3112 <<
"Exception checking transaction: " << reason;
3114 app_.getHashRouter().setFlags(stx->getTransactionID(), SF_BAD);
3115 charge(Resource::feeInvalidSignature);
3119 bool const trusted(flags & SF_TRUSTED);
3120 app_.getOPs().processTransaction(
3123 RPC::SubmitSync::async,
3125 NetworkOPs::FailHard::no);
3129 JLOG(p_journal_.warn())
3130 <<
"Exception in " << __func__ <<
": " << ex.
what();
3131 app_.getHashRouter().setFlags(stx->getTransactionID(), SF_BAD);
3132 charge(Resource::feeBadData);
3138 PeerImp::checkPropose(
3143 JLOG(p_journal_.trace())
3144 <<
"Checking " << (isTrusted ?
"trusted" :
"UNTRUSTED") <<
" proposal";
3150 JLOG(p_journal_.warn()) <<
"Proposal fails sig check";
3151 charge(Resource::feeInvalidSignature);
3158 relay = app_.getOPs().processTrustedProposal(peerPos);
3160 relay = app_.config().RELAY_UNTRUSTED_PROPOSALS == 1 || cluster();
3168 auto haveMessage = app_.overlay().relay(
3170 if (reduceRelayReady() && !haveMessage.empty())
3171 overlay_.updateSlotAndSquelch(
3174 std::move(haveMessage),
3175 protocol::mtPROPOSE_LEDGER);
3180 PeerImp::checkValidation(
3185 if (!val->isValid())
3187 JLOG(p_journal_.debug()) <<
"Validation forwarded by peer is invalid";
3188 charge(Resource::feeInvalidSignature);
3203 overlay_.relay(*packet, key, val->getSignerPublic());
3204 if (reduceRelayReady() && !haveMessage.empty())
3206 overlay_.updateSlotAndSquelch(
3208 val->getSignerPublic(),
3209 std::move(haveMessage),
3210 protocol::mtVALIDATION);
3216 JLOG(p_journal_.trace())
3217 <<
"Exception processing validation: " << ex.
what();
3218 charge(Resource::feeInvalidRequest);
3232 if (p->hasTxSet(rootHash) && p.get() != skip)
3234 auto score = p->getScore(true);
3235 if (!ret || (score > retScore))
3260 if (p->hasLedger(ledgerHash, ledger) && p.get() != skip)
3262 auto score = p->getScore(true);
3263 if (!ret || (score > retScore))
3275 PeerImp::sendLedgerBase(
3277 protocol::TMLedgerData& ledgerData)
3279 JLOG(p_journal_.trace()) <<
"sendLedgerBase: Base data";
3282 addRaw(ledger->info(), s);
3285 auto const& stateMap{ledger->stateMap()};
3286 if (stateMap.getHash() != beast::zero)
3291 stateMap.serializeRoot(
root);
3292 ledgerData.add_nodes()->set_nodedata(
3293 root.getDataPtr(),
root.getLength());
3295 if (ledger->info().txHash != beast::zero)
3297 auto const& txMap{ledger->txMap()};
3298 if (txMap.getHash() != beast::zero)
3302 txMap.serializeRoot(
root);
3303 ledgerData.add_nodes()->set_nodedata(
3304 root.getDataPtr(),
root.getLength());
3310 std::make_shared<Message>(ledgerData, protocol::mtLEDGER_DATA)};
3317 JLOG(p_journal_.trace()) <<
"getLedger: Ledger";
3321 if (m->has_ledgerhash())
3324 uint256 const ledgerHash{m->ledgerhash()};
3325 ledger = app_.getLedgerMaster().getLedgerByHash(ledgerHash);
3328 if (m->has_ledgerseq())
3331 if (
auto shards = app_.getShardStore())
3333 if (m->ledgerseq() >= shards->earliestLedgerSeq())
3336 shards->fetchLedger(ledgerHash, m->ledgerseq());
3343 JLOG(p_journal_.trace())
3344 <<
"getLedger: Don't have ledger with hash " << ledgerHash;
3346 if (m->has_querytype() && !m->has_requestcookie())
3352 m->has_ledgerseq() ? m->ledgerseq() : 0,
3355 m->set_requestcookie(
id());
3356 peer->send(std::make_shared<Message>(
3357 *m, protocol::mtGET_LEDGER));
3358 JLOG(p_journal_.debug())
3359 <<
"getLedger: Request relayed to peer";
3363 JLOG(p_journal_.trace())
3364 <<
"getLedger: Failed to find peer to relay request";
3369 else if (m->has_ledgerseq())
3372 if (m->ledgerseq() < app_.getLedgerMaster().getEarliestFetch())
3374 JLOG(p_journal_.debug())
3375 <<
"getLedger: Early ledger sequence request";
3379 ledger = app_.getLedgerMaster().getLedgerBySeq(m->ledgerseq());
3382 JLOG(p_journal_.debug())
3383 <<
"getLedger: Don't have ledger with sequence "
3388 else if (m->has_ltype() && m->ltype() == protocol::ltCLOSED)
3390 ledger = app_.getLedgerMaster().getClosedLedger();
3396 auto const ledgerSeq{ledger->info().seq};
3397 if (m->has_ledgerseq())
3399 if (ledgerSeq != m->ledgerseq())
3402 if (!m->has_requestcookie())
3403 charge(Resource::feeInvalidRequest);
3406 JLOG(p_journal_.warn())
3407 <<
"getLedger: Invalid ledger sequence " << ledgerSeq;
3410 else if (ledgerSeq < app_.getLedgerMaster().getEarliestFetch())
3413 JLOG(p_journal_.debug())
3414 <<
"getLedger: Early ledger sequence request " << ledgerSeq;
3419 JLOG(p_journal_.debug()) <<
"getLedger: Unable to find ledger";
3428 JLOG(p_journal_.trace()) <<
"getTxSet: TX set";
3430 uint256 const txSetHash{m->ledgerhash()};
3432 app_.getInboundTransactions().getSet(txSetHash,
false)};
3435 if (m->has_querytype() && !m->has_requestcookie())
3440 m->set_requestcookie(
id());
3442 std::make_shared<Message>(*m, protocol::mtGET_LEDGER));
3443 JLOG(p_journal_.debug()) <<
"getTxSet: Request relayed";
3447 JLOG(p_journal_.debug())
3448 <<
"getTxSet: Failed to find relay peer";
3453 JLOG(p_journal_.debug()) <<
"getTxSet: Failed to find TX set";
3464 if (!m->has_requestcookie())
3465 charge(Resource::feeMediumBurdenPeer);
3469 SHAMap const* map{
nullptr};
3470 protocol::TMLedgerData ledgerData;
3471 bool fatLeaves{
true};
3472 auto const itype{m->itype()};
3474 if (itype == protocol::liTS_CANDIDATE)
3476 if (sharedMap = getTxSet(m); !sharedMap)
3478 map = sharedMap.
get();
3481 ledgerData.set_ledgerseq(0);
3482 ledgerData.set_ledgerhash(m->ledgerhash());
3483 ledgerData.set_type(protocol::liTS_CANDIDATE);
3484 if (m->has_requestcookie())
3485 ledgerData.set_requestcookie(m->requestcookie());
3492 if (send_queue_.size() >= Tuning::dropSendQueue)
3494 JLOG(p_journal_.debug())
3495 <<
"processLedgerRequest: Large send queue";
3498 if (app_.getFeeTrack().isLoadedLocal() && !cluster())
3500 JLOG(p_journal_.debug()) <<
"processLedgerRequest: Too busy";
3504 if (ledger = getLedger(m); !ledger)
3508 auto const ledgerHash{ledger->info().hash};
3509 ledgerData.set_ledgerhash(ledgerHash.begin(), ledgerHash.size());
3510 ledgerData.set_ledgerseq(ledger->info().seq);
3511 ledgerData.set_type(itype);
3512 if (m->has_requestcookie())
3513 ledgerData.set_requestcookie(m->requestcookie());
3517 case protocol::liBASE:
3518 sendLedgerBase(ledger, ledgerData);
3521 case protocol::liTX_NODE:
3522 map = &ledger->txMap();
3523 JLOG(p_journal_.trace()) <<
"processLedgerRequest: TX map hash "
3524 << to_string(map->getHash());
3527 case protocol::liAS_NODE:
3528 map = &ledger->stateMap();
3529 JLOG(p_journal_.trace())
3530 <<
"processLedgerRequest: Account state map hash "
3531 << to_string(map->getHash());
3536 JLOG(p_journal_.error())
3537 <<
"processLedgerRequest: Invalid ledger info type";
3544 JLOG(p_journal_.warn()) <<
"processLedgerRequest: Unable to find map";
3549 if (m->nodeids_size() > 0)
3551 auto const queryDepth{
3552 m->has_querydepth() ? m->querydepth() : (isHighLatency() ? 2 : 1)};
3556 for (
int i = 0; i < m->nodeids_size() &&
3557 ledgerData.nodes_size() < Tuning::softMaxReplyNodes;
3563 data.reserve(Tuning::softMaxReplyNodes);
3567 if (map->getNodeFat(*shaMapNodeId, data, fatLeaves, queryDepth))
3569 JLOG(p_journal_.trace())
3570 <<
"processLedgerRequest: getNodeFat got "
3571 << data.size() <<
" nodes";
3573 for (
auto const& d : data)
3575 protocol::TMLedgerNode* node{ledgerData.add_nodes()};
3576 node->set_nodeid(d.first.getRawString());
3577 node->set_nodedata(d.second.data(), d.second.size());
3582 JLOG(p_journal_.warn())
3583 <<
"processLedgerRequest: getNodeFat returns false";
3591 case protocol::liBASE:
3593 info =
"Ledger base";
3596 case protocol::liTX_NODE:
3600 case protocol::liAS_NODE:
3604 case protocol::liTS_CANDIDATE:
3605 info =
"TS candidate";
3613 if (!m->has_ledgerhash())
3614 info +=
", no hash specified";
3616 JLOG(p_journal_.error())
3617 <<
"processLedgerRequest: getNodeFat with nodeId "
3618 << *shaMapNodeId <<
" and ledger info type " << info
3619 <<
" throws exception: " << e.
what();
3623 JLOG(p_journal_.info())
3624 <<
"processLedgerRequest: Got request for " << m->nodeids_size()
3625 <<
" nodes at depth " << queryDepth <<
", return "
3626 << ledgerData.nodes_size() <<
" nodes";
3629 send(std::make_shared<Message>(ledgerData, protocol::mtLEDGER_DATA));
3633 PeerImp::getScore(
bool haveItem)
const
3637 static const int spRandomMax = 9999;
3641 static const int spHaveItem = 10000;
3646 static const int spLatency = 30;
3649 static const int spNoLatency = 8000;
3654 score += spHaveItem;
3663 score -= latency->count() * spLatency;
3665 score -= spNoLatency;
3671 PeerImp::isHighLatency()
const
3674 return latency_ >= peerHighLatency;
3678 PeerImp::reduceRelayReady()
3680 if (!reduceRelayReady_)
3682 reduce_relay::epoch<std::chrono::minutes>(UptimeClock::now()) >
3683 reduce_relay::WAIT_ON_BOOTUP;
3684 return vpReduceRelayEnabled_ && reduceRelayReady_;
3690 using namespace std::chrono_literals;
3693 totalBytes_ += bytes;
3694 accumBytes_ += bytes;
3695 auto const timeElapsed = clock_type::now() - intervalStart_;
3696 auto const timeElapsedInSecs =
3697 std::chrono::duration_cast<std::chrono::seconds>(timeElapsed);
3699 if (timeElapsedInSecs >= 1s)
3701 auto const avgBytes = accumBytes_ / timeElapsedInSecs.count();
3702 rollingAvg_.push_back(avgBytes);
3704 auto const totalBytes =
3706 rollingAvgBytes_ = totalBytes / rollingAvg_.size();
3708 intervalStart_ = clock_type::now();
3714 PeerImp::Metrics::average_bytes()
const
3717 return rollingAvgBytes_;
3721 PeerImp::Metrics::total_bytes()
const