Remove BCLog::HEADERSSYNC and move all headerssync logging to BCLog::NET.
Bypass headers anti-DoS checks for NoBan peers
Also fix a typo that was introduced in PR25717.
Remove BCLog::HEADERSSYNC and move all headerssync logging to BCLog::NET.
Bypass headers anti-DoS checks for NoBan peers
Also fix a typo that was introduced in PR25717.
53 self.generate(self.nodes[0], NODE1_BLOCKS_REQUIRED-1, sync_fun=self.no_op)
54
55- for node in self.nodes[1:]:
56+ # Node3 should always allow headers due to noban permissions
57+ self.log.info("Check that node3 will sync headers (due to noban permissions)")
58+ def check_node3_chaintips(num_tips, tip_hash, height):
0/tmp/cirrus-ci-build/test/functional/p2p_headers_sync_with_minchainwork.py:57: unused variable 'num_tips' (100% confidence)
1test/functional/p2p_headers_sync_with_minchainwork.py:57:9: E306 expected 1 blank line before a nested definition, found 0
0diff --git a/src/net_processing.cpp b/src/net_processing.cpp
1index c4a1b5fa15..1158b6c06a 100644
2--- a/src/net_processing.cpp
3+++ b/src/net_processing.cpp
4@@ -634,23 +634,23 @@ private:
5 * acceptance by the caller).
6 */
7 bool IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom,
8- std::vector<CBlockHeader>& headers)
9+ std::vector<CBlockHeader>& headers)
10 EXCLUSIVE_LOCKS_REQUIRED(peer.m_headers_sync_mutex, !m_headers_presync_mutex);
11 /** Check work on a headers chain to be processed, and if insufficient,
12 * initiate our anti-DoS headers sync mechanism.
13 *
14- * [@param](/bitcoin-bitcoin/contributor/param/)[in] peer The peer whose headers we're processing.
15- * [@param](/bitcoin-bitcoin/contributor/param/)[in] pfrom CNode of the peer
16- * [@param](/bitcoin-bitcoin/contributor/param/)[in] chain_start_header Where these headers connect in our index.
17- * [@param](/bitcoin-bitcoin/contributor/param/)[in,out] headers The headers to be processed.
18+ * [@param](/bitcoin-bitcoin/contributor/param/)[in] peer The peer whose headers we're processing.
19+ * [@param](/bitcoin-bitcoin/contributor/param/)[in] pfrom CNode of the peer
20+ * [@param](/bitcoin-bitcoin/contributor/param/)[in] chain_start_header Where these headers connect in our index.
21+ * [@param](/bitcoin-bitcoin/contributor/param/)[in,out] headers The headers to be processed.
22 *
23 * [@return](/bitcoin-bitcoin/contributor/return/) True if chain was low work and a headers sync was
24 * initiated (and headers will be empty after calling); false
25 * otherwise.
26 */
27 bool TryLowWorkHeadersSync(Peer& peer, CNode& pfrom,
28- const CBlockIndex* chain_start_header,
29- std::vector<CBlockHeader>& headers)
30+ const CBlockIndex* chain_start_header,
31+ std::vector<CBlockHeader>& headers)
32 EXCLUSIVE_LOCKS_REQUIRED(!peer.m_headers_sync_mutex, !m_peer_mutex, !m_headers_presync_mutex);
33
34 /** Return true if the given header is an ancestor of
35@@ -1482,7 +1482,7 @@ void PeerManagerImpl::ReattemptInitialBroadcast(CScheduler& scheduler)
36
37 void PeerManagerImpl::FinalizeNode(const CNode& node)
38 {
39+ AssertLockNotHeld(m_headers_presync_mutex);
40 NodeId nodeid = node.GetId();
41 int misbehavior{0};
42 {
43@@ -2481,6 +2481,9 @@ bool PeerManagerImpl::CheckHeadersAreContinuous(const std::vector<CBlockHeader>&
44
45 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom, std::vector<CBlockHeader>& headers)
46 {
47+ AssertLockHeld(peer.m_headers_sync_mutex);
48+ AssertLockNotHeld(m_headers_presync_mutex);
49 if (peer.m_headers_sync) {
50 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() == MAX_HEADERS_RESULTS);
51 if (result.request_more) {
52@@ -2494,13 +2497,12 @@ bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfro
53 // it may be possible to bypass this via compactblock
54 // processing, so check the result before logging just to be
55 // safe.
56- bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
57- if (sent_getheaders) {
58+ if (MaybeSendGetHeaders(pfrom, locator, peer)) {
59 LogPrint(BCLog::NET, "more getheaders (from %s) to peer=%d\n",
60- locator.vHave.front().ToString(), pfrom.GetId());
61+ locator.vHave.front().ToString(), pfrom.GetId());
62 } else {
63 LogPrint(BCLog::NET, "error sending next getheaders (from %s) to continue sync with peer=%d\n",
64- locator.vHave.front().ToString(), pfrom.GetId());
65+ locator.vHave.front().ToString(), pfrom.GetId());
66 }
67 }
68 }
69@@ -2567,6 +2569,9 @@ bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfro
70
71 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer, CNode& pfrom, const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
72 {
73+ AssertLockNotHeld(peer.m_headers_sync_mutex);
74+ AssertLockNotHeld(m_peer_mutex);
75+ AssertLockNotHeld(m_headers_presync_mutex);
76 // Calculate the total work on this chain.
77 arith_uint256 total_work = chain_start_header->nChainWork + CalculateHeadersWork(headers);
78
79@@ -2609,6 +2614,7 @@ bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer, CNode& pfrom, const CBlo
80
81 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(const CBlockIndex* header)
82 {
83+ AssertLockHeld(cs_main);
84 if (header == nullptr) {
85 return false;
86 } else if (m_chainman.m_best_header != nullptr && header == m_chainman.m_best_header->GetAncestor(header->nHeight)) {
87@@ -2767,7 +2773,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
88 std::vector<CBlockHeader>&& headers,
89 bool via_compact_block)
90 {
91+ AssertLockNotHeld(m_headers_presync_mutex);
92 size_t nCount = headers.size();
93
94 if (nCount == 0) {
95@@ -3166,9 +3172,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
96 const std::chrono::microseconds time_received,
97 const std::atomic<bool>& interruptMsgProc)
98 {
99+ AssertLockNotHeld(m_headers_presync_mutex);
100
101 LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom.GetId());
Feel free to ignore. I also have a branch ready at https://github.com/bitcoin/bitcoin/compare/master...jonatack:bitcoin:net-add-missing-thread-safety-runtime-assertions for all the net and net_processing code and mention above only the runtime lock assertions directly related to changes in #25717.
Edit: updated with additional missing lock assertions.
2819@@ -2820,6 +2820,13 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
2820 }
2821 }
2822
2823+ // If our peer has NetPermissionFlags::NoBan privileges, then bypass our
2824+ // anti-DoS logic (this saves bandwidth when we connect to a trusted peer
2825+ // on startup).
2826+ if (pfrom.HasPermission(NetPermissionFlags::NoBan)) {
2827+ already_validated_work = true;
trustworthy_work
or something could be more accurate, although I’m not sure it actually benefits the readers.
tACK 94af3e43e20aa00b18e7a3f6d0f5fe3ad9494d97
I checked that NoBan
peers indeed sync in a single pass now.
The download
permission might be more suitable for this (and it’s implied by noban
). In any case it’s not a very useful optimisation, but I’m not opposed to it.
The
download
permission might be more suitable for this
For what it’s worth, I interpret download
as being more in the other direction – “this peer can download from me, even if I’m in IBD” rather than “I feel safe downloading from this peer”, so it seemed less suitable to me. But :shrug:
64@@ -65,7 +65,6 @@ namespace BCLog {
65 #endif
66 UTIL = (1 << 25),
67 BLOCKSTORE = (1 << 26),
68- HEADERSSYNC = (1 << 27),
You could make this a scripted diff:
0-BEGIN VERIFY SCRIPT-
1sed -i '/headerssync/Id' src/logging.h src/logging.cpp
2sed -i 's/BCLog::HEADERSSYNC/BCLog::NET/g' $(git grep -l BCLog::HEADERSSYNC)
3-END VERIFY SCRIPT-
We should probably document what we mean by these permissions :-)
They’re documented in bitcoin-cli help getpeerinfo
:
0 "permissions" : [ (json array) Any special permissions that have been granted to this peer
1 "str", (string) bloomfilter (allow requesting BIP37 filtered blocks and transactions),
2 noban (do not ban for misbehavior; implies download),
3 forcerelay (relay transactions that are already in the mempool; implies relay),
4 relay (relay even in -blocksonly mode, and unlimited transaction announcements),
5 mempool (allow requesting BIP35 mempool contents),
6 download (allow getheaders during IBD, no disconnect after maxuploadtarget limit),
7 addr (responses to GETADDR avoid hitting the cache and contain random records with the most up-to-date info).
8
9 ...
10 ],
and in bitcoind -help
under -whitebind
.
noban
is better. I guess download
should have been called upload
, but that depends on the perspective :-)
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.