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