v29.4-roots.2 · Commit 3: [PATCH 03/21] policy: restore conservative relay and network controls
src/net_processing.cpp
Before: src/net_processing.cpp · After: src/net_processing.cpp
File metadata
index 049812763716697b645ba5d4a6bb873e0a4511ae..de81fb24b3225c9422fbf56db9516c5669ca1f14 100644
Download original patch · Release notes
Diff rows 1–400 of 417. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
src/net_processing.cpp
CHANGED
|
@@ -10,6 +10,7 @@
|
|
| 10 |
#include <blockencodings.h>
|
| 11 |
#include <blockfilter.h>
|
| 12 |
#include <chainparams.h>
|
|
|
|
| 13 |
#include <consensus/amount.h>
|
| 14 |
#include <consensus/validation.h>
|
| 15 |
#include <deploymentstatus.h>
|
|
@@ -137,7 +138,7 @@ static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL{5s};
|
|
| 137 |
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL{2s};
|
| 138 |
/** Maximum rate of inventory items to send per second.
|
| 139 |
* Limits the impact of low-fee transaction floods. */
|
| 140 |
-
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND = 7;
|
| 141 |
/** Target number of tx inventory items to send per transmission. */
|
| 142 |
static constexpr unsigned int INVENTORY_BROADCAST_TARGET = INVENTORY_BROADCAST_PER_SECOND * count_seconds(INBOUND_INVENTORY_BROADCAST_INTERVAL);
|
| 143 |
/** Maximum number of inventory items to send per transmission. */
|
|
@@ -500,7 +501,7 @@ public:
|
|
| 500 |
/** Implement PeerManager */
|
| 501 |
void StartScheduledTasks(CScheduler& scheduler) override;
|
| 502 |
void CheckForStaleTipAndEvictPeers() override;
|
| 503 |
-
std::optional<std::string> FetchBlock(NodeId peer_id, const CBlockIndex& block_index) override
|
| 504 |
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
| 505 |
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
| 506 |
std::vector<TxOrphanage::OrphanTxBase> GetOrphanTransactions() override EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
|
|
@@ -777,7 +778,7 @@ private:
|
|
| 777 |
|
| 778 |
uint32_t GetFetchFlags(const Peer& peer) const;
|
| 779 |
|
| 780 |
-
std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
|
| 781 |
|
| 782 |
/** Number of nodes with fSyncStarted. */
|
| 783 |
int nSyncStarted GUARDED_BY(cs_main) = 0;
|
|
@@ -807,12 +808,14 @@ private:
|
|
| 807 |
|
| 808 |
/**
|
| 809 |
* For sending `inv`s to inbound peers, we use a single (exponentially
|
| 810 |
-
* distributed) timer for all peers. If we used a separate timer for each
|
| 811 |
* peer, a spy node could make multiple inbound connections to us to
|
| 812 |
-
* accurately determine when we received the transaction (and potentially
|
| 813 |
-
* determine the transaction's origin). */
|
|
|
|
| 814 |
std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
|
| 815 |
-
std::chrono::seconds average_interval) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
|
|
|
| 816 |
|
| 817 |
|
| 818 |
// All of the following cache a recent block, and are protected by m_most_recent_block_mutex
|
|
@@ -849,6 +852,9 @@ private:
|
|
| 849 |
/** Have we requested this block from an outbound peer */
|
| 850 |
bool IsBlockRequestedFromOutbound(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main, !m_peer_mutex);
|
| 851 |
|
|
|
|
|
|
|
|
|
|
| 852 |
/** Remove this block from our tracked requested blocks. Called if:
|
| 853 |
* - the block has been received from a peer
|
| 854 |
* - the request for the block has timed out
|
|
@@ -939,7 +945,7 @@ private:
|
|
| 939 |
/** Number of peers from which we're downloading blocks. */
|
| 940 |
int m_peers_downloading_from GUARDED_BY(cs_main) = 0;
|
| 941 |
|
| 942 |
-
void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
| 943 |
|
| 944 |
/** Orphan/conflicted/etc transactions that are kept for compact block reconstruction.
|
| 945 |
* The last -blockreconstructionextratxn/DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN of
|
|
@@ -947,6 +953,7 @@ private:
|
|
| 947 |
std::vector<CTransactionRef> vExtraTxnForCompact GUARDED_BY(g_msgproc_mutex);
|
| 948 |
/** Offset into vExtraTxnForCompact to insert the next tx */
|
| 949 |
size_t vExtraTxnForCompactIt GUARDED_BY(g_msgproc_mutex) = 0;
|
|
|
|
| 950 |
|
| 951 |
/** Check whether the last unknown block a peer advertised is not yet known. */
|
| 952 |
void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
|
@@ -1111,15 +1118,15 @@ static bool CanServeWitnesses(const Peer& peer)
|
|
| 1111 |
}
|
| 1112 |
|
| 1113 |
std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
|
| 1114 |
-
std::chrono::seconds average_interval)
|
|
|
|
| 1115 |
{
|
| 1116 |
-
if (m_next_inv_to_inbounds.load() < now) {
|
| 1117 |
-
// If this function were called from multiple threads simultaneously
|
| 1118 |
-
// it would possible that both update the next send variable, and return a different result to their caller.
|
| 1119 |
-
// This is not possible in practice as only the net processing thread invokes this function.
|
| 1120 |
-
m_next_inv_to_inbounds = now + m_rng.rand_exp_duration(average_interval);
|
| 1121 |
}
|
| 1122 |
-
return m_next_inv_to_inbounds;
|
| 1123 |
}
|
| 1124 |
|
| 1125 |
bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
|
|
@@ -1138,6 +1145,16 @@ bool PeerManagerImpl::IsBlockRequestedFromOutbound(const uint256& hash)
|
|
| 1138 |
return false;
|
| 1139 |
}
|
| 1140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1141 |
void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer)
|
| 1142 |
{
|
| 1143 |
auto range = mapBlocksInFlight.equal_range(hash);
|
|
@@ -1529,6 +1546,9 @@ void PeerManagerImpl::InitializeNode(const CNode& node, ServiceFlags our_service
|
|
| 1529 |
if (NetPermissions::HasFlag(node.m_permission_flags, NetPermissionFlags::BloomFilter)) {
|
| 1530 |
our_services = static_cast<ServiceFlags>(our_services | NODE_BLOOM);
|
| 1531 |
}
|
|
|
|
|
|
|
|
|
|
| 1532 |
|
| 1533 |
PeerRef peer = std::make_shared<Peer>(nodeid, our_services, node.IsInboundConn());
|
| 1534 |
{
|
|
@@ -1676,6 +1696,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
|
|
| 1676 |
if (queue.pindex)
|
| 1677 |
stats.vHeightInFlight.push_back(queue.pindex->nHeight);
|
| 1678 |
}
|
|
|
|
| 1679 |
}
|
| 1680 |
|
| 1681 |
PeerRef peer = GetPeerRef(nodeid);
|
|
@@ -1712,6 +1733,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c
|
|
| 1712 |
}
|
| 1713 |
}
|
| 1714 |
stats.time_offset = peer->m_time_offset;
|
|
|
|
| 1715 |
|
| 1716 |
return true;
|
| 1717 |
}
|
|
@@ -1730,14 +1752,27 @@ PeerManagerInfo PeerManagerImpl::GetInfo() const
|
|
| 1730 |
};
|
| 1731 |
}
|
| 1732 |
|
| 1733 |
-
void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx)
|
| 1734 |
{
|
| 1735 |
if (m_opts.max_extra_txs <= 0)
|
| 1736 |
return;
|
| 1737 |
if (!vExtraTxnForCompact.size())
|
| 1738 |
vExtraTxnForCompact.resize(m_opts.max_extra_txs);
|
| 1739 |
-
vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1740 |
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1741 |
}
|
| 1742 |
|
| 1743 |
void PeerManagerImpl::Misbehaving(Peer& peer, const std::string& message)
|
|
@@ -1753,10 +1788,23 @@ void PeerManagerImpl::Misbehaving(Peer& peer, const std::string& message)
|
|
| 1753 |
);
|
| 1754 |
}
|
| 1755 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1756 |
void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
|
| 1757 |
bool via_compact_block, const std::string& message)
|
| 1758 |
{
|
| 1759 |
-
PeerRef peer{GetPeerRef(nodeid)};
|
| 1760 |
switch (state.GetResult()) {
|
| 1761 |
case BlockValidationResult::BLOCK_RESULT_UNSET:
|
| 1762 |
break;
|
|
@@ -1768,7 +1816,7 @@ void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
|
|
| 1768 |
case BlockValidationResult::BLOCK_CONSENSUS:
|
| 1769 |
case BlockValidationResult::BLOCK_MUTATED:
|
| 1770 |
if (!via_compact_block) {
|
| 1771 |
-
if (peer) Misbehaving(*peer, message);
|
| 1772 |
return;
|
| 1773 |
}
|
| 1774 |
break;
|
|
@@ -1776,8 +1824,8 @@ void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
|
|
| 1776 |
{
|
| 1777 |
// Discourage outbound (but not inbound) peers if on an invalid chain.
|
| 1778 |
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
|
| 1779 |
-
if (peer && !via_compact_block && !peer->m_is_inbound) {
|
| 1780 |
-
if (peer) Misbehaving(*peer, message);
|
| 1781 |
return;
|
| 1782 |
}
|
| 1783 |
break;
|
|
@@ -1785,11 +1833,11 @@ void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
|
|
| 1785 |
case BlockValidationResult::BLOCK_INVALID_HEADER:
|
| 1786 |
case BlockValidationResult::BLOCK_CHECKPOINT:
|
| 1787 |
case BlockValidationResult::BLOCK_INVALID_PREV:
|
| 1788 |
-
if (peer) Misbehaving(*peer, message);
|
| 1789 |
return;
|
| 1790 |
// Conflicting (but not necessarily invalid) data or different policy:
|
| 1791 |
case BlockValidationResult::BLOCK_MISSING_PREV:
|
| 1792 |
-
if (peer) Misbehaving(*peer, message);
|
| 1793 |
return;
|
| 1794 |
case BlockValidationResult::BLOCK_TIME_FUTURE:
|
| 1795 |
break;
|
|
@@ -1808,7 +1856,7 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex)
|
|
| 1808 |
(GetBlockProofEquivalentTime(*m_chainman.m_best_header, *pindex, *m_chainman.m_best_header, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT);
|
| 1809 |
}
|
| 1810 |
|
| 1811 |
-
std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBlockIndex& block_index)
|
| 1812 |
{
|
| 1813 |
if (m_chainman.m_blockman.LoadingBlocks()) return "Loading blocks ...";
|
| 1814 |
|
|
@@ -1821,14 +1869,18 @@ std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBl
|
|
| 1821 |
|
| 1822 |
LOCK(cs_main);
|
| 1823 |
|
| 1824 |
-
// Forget about all prior requests
|
| 1825 |
-
RemoveBlockRequest(block_index.GetBlockHash(), std::nullopt);
|
| 1826 |
|
| 1827 |
-
// Mark block as in-flight
|
| 1828 |
-
if (!BlockRequested(peer_id, block_index)) return "Already requested from this peer";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1829 |
|
| 1830 |
// Construct message to request the block
|
| 1831 |
-
const uint256& hash{block_index.GetBlockHash()};
|
| 1832 |
std::vector<CInv> invs{CInv(MSG_BLOCK | MSG_WITNESS_FLAG, hash)};
|
| 1833 |
|
| 1834 |
// Send block request message to the peer
|
|
@@ -1844,6 +1896,12 @@ std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const CBl
|
|
| 1844 |
return std::nullopt;
|
| 1845 |
}
|
| 1846 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1847 |
std::unique_ptr<PeerManager> PeerManager::make(CConnman& connman, AddrMan& addrman,
|
| 1848 |
BanMan* banman, ChainstateManager& chainman,
|
| 1849 |
CTxMemPool& pool, node::Warnings& warnings, Options opts)
|
|
@@ -1851,11 +1909,12 @@ std::unique_ptr<PeerManager> PeerManager::make(CConnman& connman, AddrMan& addrm
|
|
| 1851 |
return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
|
| 1852 |
}
|
| 1853 |
|
|
|
|
| 1854 |
PeerManagerImpl::PeerManagerImpl(CConnman& connman, AddrMan& addrman,
|
| 1855 |
BanMan* banman, ChainstateManager& chainman,
|
| 1856 |
CTxMemPool& pool, node::Warnings& warnings, Options opts)
|
| 1857 |
: m_rng{opts.deterministic_rng},
|
| 1858 |
-
m_fee_filter_rounder{CFeeRate{DEFAULT_MIN_RELAY_TX_FEE}, m_rng},
|
| 1859 |
m_chainparams(chainman.GetParams()),
|
| 1860 |
m_connman(connman),
|
| 1861 |
m_addrman(addrman),
|
|
@@ -2208,7 +2267,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
|
|
| 2208 |
}
|
| 2209 |
// disconnect node in case we have reached the outbound limit for serving historical blocks
|
| 2210 |
if (m_connman.OutboundTargetReached(true) &&
|
| 2211 |
-
(((m_chainman.m_best_header != nullptr) && (m_chainman.m_best_header->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk()) &&
|
| 2212 |
!pfrom.HasPermission(NetPermissionFlags::Download) // nodes with the download permission may exceed target
|
| 2213 |
) {
|
| 2214 |
LogDebug(BCLog::NET, "historical block serving limit reached, %s\n", pfrom.DisconnectMsg(fLogIPs));
|
|
@@ -2271,7 +2330,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
|
|
| 2271 |
MakeAndPushMessage(pfrom, NetMsgType::BLOCK, TX_NO_WITNESS(*pblock));
|
| 2272 |
} else if (inv.IsMsgWitnessBlk()) {
|
| 2273 |
MakeAndPushMessage(pfrom, NetMsgType::BLOCK, TX_WITH_WITNESS(*pblock));
|
| 2274 |
-
} else if (inv.IsMsgFilteredBlk()) {
|
| 2275 |
bool sendMerkleBlock = false;
|
| 2276 |
CMerkleBlock merkleBlock;
|
| 2277 |
if (auto tx_relay = peer.GetTxRelay(); tx_relay != nullptr) {
|
|
@@ -2289,9 +2348,10 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv&
|
|
| 2289 |
// they must either disconnect and retry or request the full block.
|
| 2290 |
// Thus, the protocol spec specified allows for us to provide duplicate txn here,
|
| 2291 |
// however we MUST always provide at least what the remote peer needs
|
|
|
|
| 2292 |
typedef std::pair<unsigned int, uint256> PairType;
|
| 2293 |
for (PairType& pair : merkleBlock.vMatchedTxn)
|
| 2294 |
-
MakeAndPushMessage(pfrom, NetMsgType::TX, TX_NO_WITNESS(*pblock->vtx[pair.first]));
|
| 2295 |
}
|
| 2296 |
// else
|
| 2297 |
// no response
|
|
@@ -2492,6 +2552,10 @@ void PeerManagerImpl::HandleUnconnectingHeaders(CNode& pfrom, Peer& peer,
|
|
| 2492 |
// eventually get the headers - even from a different peer -
|
| 2493 |
// we can use this peer to download.
|
| 2494 |
WITH_LOCK(cs_main, UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash()));
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2495 |
}
|
| 2496 |
|
| 2497 |
bool PeerManagerImpl::CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const
|
|
@@ -2948,8 +3012,9 @@ std::optional<node::PackageToValidate> PeerManagerImpl::ProcessInvalidTx(NodeId
|
|
| 2948 |
|
| 2949 |
const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
|
| 2950 |
|
| 2951 |
-
if (add_extra_compact_tx && RecursiveDynamicUsage(*ptx) < 100000) {
|
| 2952 |
-
AddToCompactExtraTransactions(ptx);
|
|
|
|
| 2953 |
}
|
| 2954 |
for (const Txid& parent_txid : unique_parents) {
|
| 2955 |
if (peer) AddKnownTx(*peer, parent_txid);
|
|
@@ -2975,7 +3040,8 @@ void PeerManagerImpl::ProcessValidTx(NodeId nodeid, const CTransactionRef& tx, c
|
|
| 2975 |
RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
|
| 2976 |
|
| 2977 |
for (const CTransactionRef& removedTx : replaced_transactions) {
|
| 2978 |
-
AddToCompactExtraTransactions(removedTx);
|
|
|
|
| 2979 |
}
|
| 2980 |
}
|
| 2981 |
|
|
@@ -3405,7 +3471,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|
| 3405 |
if (!vRecv.empty()) {
|
| 3406 |
std::string strSubVer;
|
| 3407 |
vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
|
| 3408 |
-
cleanSubVer = SanitizeString(strSubVer);
|
| 3409 |
}
|
| 3410 |
if (!vRecv.empty()) {
|
| 3411 |
vRecv >> starting_height;
|
|
@@ -3434,6 +3500,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|
| 3434 |
// Change version
|
| 3435 |
const int greatest_common_version = std::min(nVersion, PROTOCOL_VERSION);
|
| 3436 |
pfrom.SetCommonVersion(greatest_common_version);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3437 |
pfrom.nVersion = nVersion;
|
| 3438 |
|
| 3439 |
if (greatest_common_version >= WTXID_RELAY_VERSION) {
|
|
@@ -3452,10 +3522,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|
| 3452 |
pfrom.m_has_all_wanted_services = HasAllDesirableServiceFlags(nServices);
|
| 3453 |
peer->m_their_services = nServices;
|
| 3454 |
pfrom.SetAddrLocal(addrMe);
|
| 3455 |
-
{
|
| 3456 |
-
LOCK(pfrom.m_subver_mutex);
|
| 3457 |
-
pfrom.cleanSubVer = cleanSubVer;
|
| 3458 |
-
}
|
| 3459 |
peer->m_starting_height = starting_height;
|
| 3460 |
|
| 3461 |
// Only initialize the Peer::TxRelay m_relay_txs data structure if:
|
|
@@ -3541,10 +3607,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|
| 3541 |
}
|
| 3542 |
|
| 3543 |
const auto mapped_as{m_connman.GetMappedAS(pfrom.addr)};
|
| 3544 |
-
LogDebug(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
|
| 3545 |
-
cleanSubVer, pfrom.nVersion,
|
| 3546 |
peer->m_starting_height, addrMe.ToStringAddrPort(), fRelay, pfrom.GetId(),
|
| 3547 |
-
pfrom.LogIP(fLogIPs), (mapped_as ? strprintf(", mapped_as=%d", mapped_as) : ""));
|
|
|
|
| 3548 |
|
| 3549 |
peer->m_time_offset = NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
|
| 3550 |
if (!pfrom.IsInboundConn()) {
|
|
@@ -3584,11 +3651,12 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|
| 3584 |
// can be triggered by an attacker at high rate.
|
| 3585 |
if (!pfrom.IsInboundConn() || LogAcceptCategory(BCLog::NET, BCLog::Level::Debug)) {
|
| 3586 |
const auto mapped_as{m_connman.GetMappedAS(pfrom.addr)};
|
| 3587 |
-
LogPrintf("New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
|
| 3588 |
pfrom.ConnectionTypeAsString(),
|
| 3589 |
TransportTypeAsString(pfrom.m_transport->GetInfo().transport_type),
|
| 3590 |
pfrom.nVersion.load(), peer->m_starting_height,
|
| 3591 |
-
pfrom.GetId(), pfrom.LogIP(fLogIPs),
|
|
|
|
| 3592 |
(mapped_as ? strprintf(", mapped_as=%d", mapped_as) : ""));
|
| 3593 |
}
|
| 3594 |
|
|
@@ -4871,13 +4939,13 @@ bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer)
|
|
| 4871 |
|
| 4872 |
if (pnode.HasPermission(NetPermissionFlags::NoBan)) {
|
| 4873 |
// We never disconnect or discourage peers for bad behavior if they have NetPermissionFlags::NoBan permission
|
| 4874 |
-
LogPrintf("Warning: not punishing noban peer %d!\n", peer.m_id);
|
| 4875 |
return false;
|
| 4876 |
}
|
| 4877 |
|
| 4878 |
if (pnode.IsManualConn()) {
|
| 4879 |
// We never disconnect or discourage manual peers for bad behavior
|
| 4880 |
-
LogPrintf("Warning: not punishing manually connected peer %d!\n", peer.m_id);
|
| 4881 |
return false;
|
|
|
|
| 10 |
#include <blockencodings.h>
|
| 11 |
#include <blockfilter.h>
|
| 12 |
#include <chainparams.h>
|
| 13 |
+
#include <common/args.h>
|
| 14 |
#include <consensus/amount.h>
|
| 15 |
#include <consensus/validation.h>
|
| 16 |
#include <deploymentstatus.h>
|
|
|
|
| 138 |
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL{2s};
|
| 139 |
/** Maximum rate of inventory items to send per second.
|
| 140 |
* Limits the impact of low-fee transaction floods. */
|
| 141 |
+
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND{14};
|
| 142 |
/** Target number of tx inventory items to send per transmission. */
|
| 143 |
static constexpr unsigned int INVENTORY_BROADCAST_TARGET = INVENTORY_BROADCAST_PER_SECOND * count_seconds(INBOUND_INVENTORY_BROADCAST_INTERVAL);
|
| 144 |
/** Maximum number of inventory items to send per transmission. */
|
|
|
|
| 501 |
/** Implement PeerManager */
|
| 502 |
void StartScheduledTasks(CScheduler& scheduler) override;
|
| 503 |
void CheckForStaleTipAndEvictPeers() override;
|
| 504 |
+
std::optional<std::string> FetchBlock(NodeId peer_id, const uint256& hash, const CBlockIndex* block_index) override
|
| 505 |
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
| 506 |
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
| 507 |
std::vector<TxOrphanage::OrphanTxBase> GetOrphanTransactions() override EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
|
|
|
|
| 778 |
|
| 779 |
uint32_t GetFetchFlags(const Peer& peer) const;
|
| 780 |
|
| 781 |
+
std::map<uint64_t, std::chrono::microseconds> m_next_inv_to_inbounds_per_network_key GUARDED_BY(g_msgproc_mutex);
|
| 782 |
|
| 783 |
/** Number of nodes with fSyncStarted. */
|
| 784 |
int nSyncStarted GUARDED_BY(cs_main) = 0;
|
|
|
|
| 808 |
|
| 809 |
/**
|
| 810 |
* For sending `inv`s to inbound peers, we use a single (exponentially
|
| 811 |
+
* distributed) timer for all peers with the same network key. If we used a separate timer for each
|
| 812 |
* peer, a spy node could make multiple inbound connections to us to
|
| 813 |
+
* accurately determine when we received a transaction (and potentially
|
| 814 |
+
* determine the transaction's origin). Each network key has its own timer
|
| 815 |
+
* to make fingerprinting harder. */
|
| 816 |
std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
|
| 817 |
+
std::chrono::seconds average_interval,
|
| 818 |
+
uint64_t network_key) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
| 819 |
|
| 820 |
|
| 821 |
// All of the following cache a recent block, and are protected by m_most_recent_block_mutex
|
|
|
|
| 852 |
/** Have we requested this block from an outbound peer */
|
| 853 |
bool IsBlockRequestedFromOutbound(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main, !m_peer_mutex);
|
| 854 |
|
| 855 |
+
/** Have we requested this block from a specific peer */
|
| 856 |
+
bool IsBlockRequestedFromPeer(const uint256& hash, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
| 857 |
+
|
| 858 |
/** Remove this block from our tracked requested blocks. Called if:
|
| 859 |
* - the block has been received from a peer
|
| 860 |
* - the request for the block has timed out
|
|
|
|
| 945 |
/** Number of peers from which we're downloading blocks. */
|
| 946 |
int m_peers_downloading_from GUARDED_BY(cs_main) = 0;
|
| 947 |
|
| 948 |
+
void AddToCompactExtraTransactions(const CTransactionRef& tx, size_t tx_dynamic_usage) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
| 949 |
|
| 950 |
/** Orphan/conflicted/etc transactions that are kept for compact block reconstruction.
|
| 951 |
* The last -blockreconstructionextratxn/DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN of
|
|
|
|
| 953 |
std::vector<CTransactionRef> vExtraTxnForCompact GUARDED_BY(g_msgproc_mutex);
|
| 954 |
/** Offset into vExtraTxnForCompact to insert the next tx */
|
| 955 |
size_t vExtraTxnForCompactIt GUARDED_BY(g_msgproc_mutex) = 0;
|
| 956 |
+
size_t blockreconstructionextratxn_memusage{0};
|
| 957 |
|
| 958 |
/** Check whether the last unknown block a peer advertised is not yet known. */
|
| 959 |
void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
|
|
|
| 1118 |
}
|
| 1119 |
|
| 1120 |
std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
|
| 1121 |
+
std::chrono::seconds average_interval,
|
| 1122 |
+
uint64_t network_key)
|
| 1123 |
{
|
| 1124 |
+
auto [it, inserted] = m_next_inv_to_inbounds_per_network_key.try_emplace(network_key, 0us);
|
| 1125 |
+
auto& timer{it->second};
|
| 1126 |
+
if (timer < now) {
|
| 1127 |
+
timer = now + m_rng.rand_exp_duration(average_interval);
|
|
|
|
| 1128 |
}
|
| 1129 |
+
return timer;
|
| 1130 |
}
|
| 1131 |
|
| 1132 |
bool PeerManagerImpl::IsBlockRequested(const uint256& hash)
|
|
|
|
| 1145 |
return false;
|
| 1146 |
}
|
| 1147 |
|
| 1148 |
+
bool PeerManagerImpl::IsBlockRequestedFromPeer(const uint256& hash, NodeId peer)
|
| 1149 |
+
{
|
| 1150 |
+
for (auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
|
| 1151 |
+
auto [nodeid, block_it] = range.first->second;
|
| 1152 |
+
if (nodeid == peer) return true;
|
| 1153 |
+
}
|
| 1154 |
+
|
| 1155 |
+
return false;
|
| 1156 |
+
}
|
| 1157 |
+
|
| 1158 |
void PeerManagerImpl::RemoveBlockRequest(const uint256& hash, std::optional<NodeId> from_peer)
|
| 1159 |
{
|
| 1160 |
auto range = mapBlocksInFlight.equal_range(hash);
|
|
|
|
| 1546 |
if (NetPermissions::HasFlag(node.m_permission_flags, NetPermissionFlags::BloomFilter)) {
|
| 1547 |
our_services = static_cast<ServiceFlags>(our_services | NODE_BLOOM);
|
| 1548 |
}
|
| 1549 |
+
if (NetPermissions::HasFlag(node.m_permission_flags, NetPermissionFlags::BlockFilters)) {
|
| 1550 |
+
our_services = static_cast<ServiceFlags>(our_services | NODE_COMPACT_FILTERS);
|
| 1551 |
+
}
|
| 1552 |
|
| 1553 |
PeerRef peer = std::make_shared<Peer>(nodeid, our_services, node.IsInboundConn());
|
| 1554 |
{
|
|
|
|
| 1696 |
if (queue.pindex)
|
| 1697 |
stats.vHeightInFlight.push_back(queue.pindex->nHeight);
|
| 1698 |
}
|
| 1699 |
+
stats.m_last_block_announcement = NodeSeconds{std::chrono::seconds{state->m_last_block_announcement}};
|
| 1700 |
}
|
| 1701 |
|
| 1702 |
PeerRef peer = GetPeerRef(nodeid);
|
|
|
|
| 1733 |
}
|
| 1734 |
}
|
| 1735 |
stats.time_offset = peer->m_time_offset;
|
| 1736 |
+
stats.m_misbehavior_score = WITH_LOCK(peer->m_misbehavior_mutex, return peer->m_should_discourage) ? 100 : 0;
|
| 1737 |
|
| 1738 |
return true;
|
| 1739 |
}
|
|
|
|
| 1752 |
};
|
| 1753 |
}
|
| 1754 |
|
| 1755 |
+
void PeerManagerImpl::AddToCompactExtraTransactions(const CTransactionRef& tx, const size_t tx_dynamic_usage)
|
| 1756 |
{
|
| 1757 |
if (m_opts.max_extra_txs <= 0)
|
| 1758 |
return;
|
| 1759 |
if (!vExtraTxnForCompact.size())
|
| 1760 |
vExtraTxnForCompact.resize(m_opts.max_extra_txs);
|
| 1761 |
+
|
| 1762 |
+
{
|
| 1763 |
+
auto& entry = vExtraTxnForCompact[vExtraTxnForCompactIt];
|
| 1764 |
+
if (entry) blockreconstructionextratxn_memusage -= RecursiveDynamicUsage(*entry);
|
| 1765 |
+
entry = tx;
|
| 1766 |
+
blockreconstructionextratxn_memusage += tx_dynamic_usage;
|
| 1767 |
+
}
|
| 1768 |
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
|
| 1769 |
+
|
| 1770 |
+
while (blockreconstructionextratxn_memusage > m_opts.max_extra_txs_size) {
|
| 1771 |
+
auto& entry = vExtraTxnForCompact[vExtraTxnForCompactIt];
|
| 1772 |
+
if (entry) blockreconstructionextratxn_memusage -= RecursiveDynamicUsage(*entry);
|
| 1773 |
+
entry.reset();
|
| 1774 |
+
vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
|
| 1775 |
+
}
|
| 1776 |
}
|
| 1777 |
|
| 1778 |
void PeerManagerImpl::Misbehaving(Peer& peer, const std::string& message)
|
|
|
|
| 1788 |
);
|
| 1789 |
}
|
| 1790 |
|
| 1791 |
+
static void HandleDoSPunishment(CConnman& connman, NodeId node_id, const int nDoS, const char * const what_is_it) {
|
| 1792 |
+
// We never actually DoS ban for invalid blocks, merely disconnect nodes if we're relying on them as a primary node
|
| 1793 |
+
const std::string msg = strprintf("peer=%d got DoS score %d on invalid %s", node_id, nDoS, what_is_it);
|
| 1794 |
+
connman.ForNode(node_id, [msg](CNode* node) {
|
| 1795 |
+
if (node->PunishInvalidBlocks()) {
|
| 1796 |
+
LogDebug(BCLog::NET, "%s; simply disconnecting\n", msg);
|
| 1797 |
+
node->fDisconnect = true;
|
| 1798 |
+
} else {
|
| 1799 |
+
LogDebug(BCLog::NET, "%s; tolerating\n", msg);
|
| 1800 |
+
}
|
| 1801 |
+
return true;
|
| 1802 |
+
});
|
| 1803 |
+
}
|
| 1804 |
+
|
| 1805 |
void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
|
| 1806 |
bool via_compact_block, const std::string& message)
|
| 1807 |
{
|
|
|
|
| 1808 |
switch (state.GetResult()) {
|
| 1809 |
case BlockValidationResult::BLOCK_RESULT_UNSET:
|
| 1810 |
break;
|
|
|
|
| 1816 |
case BlockValidationResult::BLOCK_CONSENSUS:
|
| 1817 |
case BlockValidationResult::BLOCK_MUTATED:
|
| 1818 |
if (!via_compact_block) {
|
| 1819 |
+
HandleDoSPunishment(m_connman, nodeid, 100, "block");
|
| 1820 |
return;
|
| 1821 |
}
|
| 1822 |
break;
|
|
|
|
| 1824 |
{
|
| 1825 |
// Discourage outbound (but not inbound) peers if on an invalid chain.
|
| 1826 |
// Exempt HB compact block peers. Manual connections are always protected from discouragement.
|
| 1827 |
+
if (!via_compact_block) {
|
| 1828 |
+
HandleDoSPunishment(m_connman, nodeid, 100, "block");
|
| 1829 |
return;
|
| 1830 |
}
|
| 1831 |
break;
|
|
|
|
| 1833 |
case BlockValidationResult::BLOCK_INVALID_HEADER:
|
| 1834 |
case BlockValidationResult::BLOCK_CHECKPOINT:
|
| 1835 |
case BlockValidationResult::BLOCK_INVALID_PREV:
|
| 1836 |
+
HandleDoSPunishment(m_connman, nodeid, 100, "block header");
|
| 1837 |
return;
|
| 1838 |
// Conflicting (but not necessarily invalid) data or different policy:
|
| 1839 |
case BlockValidationResult::BLOCK_MISSING_PREV:
|
| 1840 |
+
HandleDoSPunishment(m_connman, nodeid, 100, "block header");
|
| 1841 |
return;
|
| 1842 |
case BlockValidationResult::BLOCK_TIME_FUTURE:
|
| 1843 |
break;
|
|
|
|
| 1856 |
(GetBlockProofEquivalentTime(*m_chainman.m_best_header, *pindex, *m_chainman.m_best_header, m_chainparams.GetConsensus()) < STALE_RELAY_AGE_LIMIT);
|
| 1857 |
}
|
| 1858 |
|
| 1859 |
+
std::optional<std::string> PeerManagerImpl::FetchBlock(NodeId peer_id, const uint256& hash, const CBlockIndex* block_index)
|
| 1860 |
{
|
| 1861 |
if (m_chainman.m_blockman.LoadingBlocks()) return "Loading blocks ...";
|
| 1862 |
|
|
|
|
| 1869 |
|
| 1870 |
LOCK(cs_main);
|
| 1871 |
|
| 1872 |
+
if (IsBlockRequestedFromPeer(hash, peer_id)) return "Already requested from this peer";
|
|
|
|
| 1873 |
|
| 1874 |
+
// Mark block as in-flight unless we don't have the header.
|
| 1875 |
+
if (block_index != nullptr) {
|
| 1876 |
+
// Forget about all prior requests
|
| 1877 |
+
RemoveBlockRequest(hash, std::nullopt);
|
| 1878 |
+
|
| 1879 |
+
// Mark block as in-flight
|
| 1880 |
+
Assume(BlockRequested(peer_id, *block_index));
|
| 1881 |
+
}
|
| 1882 |
|
| 1883 |
// Construct message to request the block
|
|
|
|
| 1884 |
std::vector<CInv> invs{CInv(MSG_BLOCK | MSG_WITNESS_FLAG, hash)};
|
| 1885 |
|
| 1886 |
// Send block request message to the peer
|
|
|
|
| 1896 |
return std::nullopt;
|
| 1897 |
}
|
| 1898 |
|
| 1899 |
+
std::optional<std::string> PeerManager::FetchBlock(NodeId peer_id, const CBlockIndex& block_index)
|
| 1900 |
+
{
|
| 1901 |
+
const uint256& hash{block_index.GetBlockHash()};
|
| 1902 |
+
return FetchBlock(peer_id, hash, &block_index);
|
| 1903 |
+
}
|
| 1904 |
+
|
| 1905 |
std::unique_ptr<PeerManager> PeerManager::make(CConnman& connman, AddrMan& addrman,
|
| 1906 |
BanMan* banman, ChainstateManager& chainman,
|
| 1907 |
CTxMemPool& pool, node::Warnings& warnings, Options opts)
|
|
|
|
| 1909 |
return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, warnings, opts);
|
| 1910 |
}
|
| 1911 |
|
| 1912 |
+
static_assert(CORE_INCREMENTAL_RELAY_FEE < DEFAULT_INCREMENTAL_RELAY_FEE, "Trinary logic for m_fee_filter_rounder is based on assumption that CORE_INCREMENTAL_RELAY_FEE is less than DEFAULT_INCREMENTAL_RELAY_FEE");
|
| 1913 |
PeerManagerImpl::PeerManagerImpl(CConnman& connman, AddrMan& addrman,
|
| 1914 |
BanMan* banman, ChainstateManager& chainman,
|
| 1915 |
CTxMemPool& pool, node::Warnings& warnings, Options opts)
|
| 1916 |
: m_rng{opts.deterministic_rng},
|
| 1917 |
+
m_fee_filter_rounder{CFeeRate{pool.m_opts.incremental_relay_feerate.GetFeePerK() < DEFAULT_INCREMENTAL_RELAY_FEE ? CORE_INCREMENTAL_RELAY_FEE : DEFAULT_INCREMENTAL_RELAY_FEE}, m_rng},
|
| 1918 |
m_chainparams(chainman.GetParams()),
|
| 1919 |
m_connman(connman),
|
| 1920 |
m_addrman(addrman),
|
|
|
|
| 2267 |
}
|
| 2268 |
// disconnect node in case we have reached the outbound limit for serving historical blocks
|
| 2269 |
if (m_connman.OutboundTargetReached(true) &&
|
| 2270 |
+
(((m_chainman.m_best_header != nullptr) && (m_chainman.m_best_header->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.IsMsgFilteredBlk() || inv.IsMsgFilteredWitnessBlk()) &&
|
| 2271 |
!pfrom.HasPermission(NetPermissionFlags::Download) // nodes with the download permission may exceed target
|
| 2272 |
) {
|
| 2273 |
LogDebug(BCLog::NET, "historical block serving limit reached, %s\n", pfrom.DisconnectMsg(fLogIPs));
|
|
|
|
| 2330 |
MakeAndPushMessage(pfrom, NetMsgType::BLOCK, TX_NO_WITNESS(*pblock));
|
| 2331 |
} else if (inv.IsMsgWitnessBlk()) {
|
| 2332 |
MakeAndPushMessage(pfrom, NetMsgType::BLOCK, TX_WITH_WITNESS(*pblock));
|
| 2333 |
+
} else if (inv.IsMsgFilteredBlk() || inv.IsMsgFilteredWitnessBlk()) {
|
| 2334 |
bool sendMerkleBlock = false;
|
| 2335 |
CMerkleBlock merkleBlock;
|
| 2336 |
if (auto tx_relay = peer.GetTxRelay(); tx_relay != nullptr) {
|
|
|
|
| 2348 |
// they must either disconnect and retry or request the full block.
|
| 2349 |
// Thus, the protocol spec specified allows for us to provide duplicate txn here,
|
| 2350 |
// however we MUST always provide at least what the remote peer needs
|
| 2351 |
+
const auto maybe_with_witness = (inv.IsMsgFilteredWitnessBlk() ? TX_WITH_WITNESS : TX_NO_WITNESS);
|
| 2352 |
typedef std::pair<unsigned int, uint256> PairType;
|
| 2353 |
for (PairType& pair : merkleBlock.vMatchedTxn)
|
| 2354 |
+
MakeAndPushMessage(pfrom, NetMsgType::TX, maybe_with_witness(*pblock->vtx[pair.first]));
|
| 2355 |
}
|
| 2356 |
// else
|
| 2357 |
// no response
|
|
|
|
| 2552 |
// eventually get the headers - even from a different peer -
|
| 2553 |
// we can use this peer to download.
|
| 2554 |
WITH_LOCK(cs_main, UpdateBlockAvailability(pfrom.GetId(), headers.back().GetHash()));
|
| 2555 |
+
|
| 2556 |
+
if (pfrom.PunishInvalidBlocks()) {
|
| 2557 |
+
pfrom.fDisconnect = true;
|
| 2558 |
+
}
|
| 2559 |
}
|
| 2560 |
|
| 2561 |
bool PeerManagerImpl::CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const
|
|
|
|
| 3012 |
|
| 3013 |
const auto& [add_extra_compact_tx, unique_parents, package_to_validate] = m_txdownloadman.MempoolRejectedTx(ptx, state, nodeid, first_time_failure);
|
| 3014 |
|
| 3015 |
+
const size_t tx_dynamic_usage{RecursiveDynamicUsage(*ptx)};
|
| 3016 |
+
if (add_extra_compact_tx && tx_dynamic_usage < BLOCK_RECONSTRUCTION_EXTRA_TXN_PER_TXN_SIZE_LIMIT) {
|
| 3017 |
+
AddToCompactExtraTransactions(ptx, tx_dynamic_usage);
|
| 3018 |
}
|
| 3019 |
for (const Txid& parent_txid : unique_parents) {
|
| 3020 |
if (peer) AddKnownTx(*peer, parent_txid);
|
|
|
|
| 3040 |
RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
|
| 3041 |
|
| 3042 |
for (const CTransactionRef& removedTx : replaced_transactions) {
|
| 3043 |
+
const size_t tx_dynamic_usage{RecursiveDynamicUsage(*removedTx)};
|
| 3044 |
+
AddToCompactExtraTransactions(removedTx, tx_dynamic_usage);
|
| 3045 |
}
|
| 3046 |
}
|
| 3047 |
|
|
|
|
| 3471 |
if (!vRecv.empty()) {
|
| 3472 |
std::string strSubVer;
|
| 3473 |
vRecv >> LIMITED_STRING(strSubVer, MAX_SUBVERSION_LENGTH);
|
| 3474 |
+
cleanSubVer = SanitizeString(strSubVer, SAFE_CHARS_PRINTABLE);
|
| 3475 |
}
|
| 3476 |
if (!vRecv.empty()) {
|
| 3477 |
vRecv >> starting_height;
|
|
|
|
| 3500 |
// Change version
|
| 3501 |
const int greatest_common_version = std::min(nVersion, PROTOCOL_VERSION);
|
| 3502 |
pfrom.SetCommonVersion(greatest_common_version);
|
| 3503 |
+
{
|
| 3504 |
+
LOCK(pfrom.m_subver_mutex);
|
| 3505 |
+
pfrom.cleanSubVer = cleanSubVer;
|
| 3506 |
+
}
|
| 3507 |
pfrom.nVersion = nVersion;
|
| 3508 |
|
| 3509 |
if (greatest_common_version >= WTXID_RELAY_VERSION) {
|
|
|
|
| 3522 |
pfrom.m_has_all_wanted_services = HasAllDesirableServiceFlags(nServices);
|
| 3523 |
peer->m_their_services = nServices;
|
| 3524 |
pfrom.SetAddrLocal(addrMe);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3525 |
peer->m_starting_height = starting_height;
|
| 3526 |
|
| 3527 |
// Only initialize the Peer::TxRelay m_relay_txs data structure if:
|
|
|
|
| 3607 |
}
|
| 3608 |
|
| 3609 |
const auto mapped_as{m_connman.GetMappedAS(pfrom.addr)};
|
| 3610 |
+
LogDebug(BCLog::NET, "receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s%s\n",
|
| 3611 |
+
SanitizeString(cleanSubVer, SAFE_CHARS_DEFAULT, true), pfrom.nVersion,
|
| 3612 |
peer->m_starting_height, addrMe.ToStringAddrPort(), fRelay, pfrom.GetId(),
|
| 3613 |
+
fLogIPs ? "," : "", pfrom.LogIP(fLogIPs),
|
| 3614 |
+
(mapped_as ? strprintf(", mapped_as=%d", mapped_as) : ""));
|
| 3615 |
|
| 3616 |
peer->m_time_offset = NodeSeconds{std::chrono::seconds{nTime}} - Now<NodeSeconds>();
|
| 3617 |
if (!pfrom.IsInboundConn()) {
|
|
|
|
| 3651 |
// can be triggered by an attacker at high rate.
|
| 3652 |
if (!pfrom.IsInboundConn() || LogAcceptCategory(BCLog::NET, BCLog::Level::Debug)) {
|
| 3653 |
const auto mapped_as{m_connman.GetMappedAS(pfrom.addr)};
|
| 3654 |
+
LogPrintf("New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s%s\n",
|
| 3655 |
pfrom.ConnectionTypeAsString(),
|
| 3656 |
TransportTypeAsString(pfrom.m_transport->GetInfo().transport_type),
|
| 3657 |
pfrom.nVersion.load(), peer->m_starting_height,
|
| 3658 |
+
pfrom.GetId(),
|
| 3659 |
+
fLogIPs ? "," : "", pfrom.LogIP(fLogIPs),
|
| 3660 |
(mapped_as ? strprintf(", mapped_as=%d", mapped_as) : ""));
|
| 3661 |
}
|
| 3662 |
|
|
|
|
| 4939 |
|
| 4940 |
if (pnode.HasPermission(NetPermissionFlags::NoBan)) {
|
| 4941 |
// We never disconnect or discourage peers for bad behavior if they have NetPermissionFlags::NoBan permission
|
| 4942 |
+
LogWarning("Not punishing noban peer %d!", peer.m_id);
|
| 4943 |
return false;
|
| 4944 |
}
|
| 4945 |
|
| 4946 |
if (pnode.IsManualConn()) {
|
| 4947 |
// We never disconnect or discourage manual peers for bad behavior
|
| 4948 |
+
LogWarning("Not punishing manually connected peer %d!", peer.m_id);
|
| 4949 |
return false;
|