Skip to content

Commit e5982ec

Browse files
committed
Bypass headers anti-DoS checks for NoBan peers
1 parent 132ed7e commit e5982ec

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/net_processing.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2820,6 +2820,13 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
28202820
}
28212821
}
28222822

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;
2828+
}
2829+
28232830
// At this point, the headers connect to something in our block index.
28242831
// Do anti-DoS checks to determine if we should process or store for later
28252832
// processing.

test/functional/p2p_headers_sync_with_minchainwork.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
2929
def set_test_params(self):
3030
self.setup_clean_chain = True
31-
self.num_nodes = 3
31+
self.num_nodes = 4
3232
# Node0 has no required chainwork; node1 requires 15 blocks on top of the genesis block; node2 requires 2047
33-
self.extra_args = [["-minimumchainwork=0x0", "-checkblockindex=0"], ["-minimumchainwork=0x1f", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0"]]
33+
self.extra_args = [["-minimumchainwork=0x0", "-checkblockindex=0"], ["-minimumchainwork=0x1f", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0", "[email protected]"]]
3434

3535
def setup_network(self):
3636
self.setup_nodes()
@@ -40,17 +40,34 @@ def setup_network(self):
4040
def disconnect_all(self):
4141
self.disconnect_nodes(0, 1)
4242
self.disconnect_nodes(0, 2)
43+
self.disconnect_nodes(0, 3)
4344

4445
def reconnect_all(self):
4546
self.connect_nodes(0, 1)
4647
self.connect_nodes(0, 2)
48+
self.connect_nodes(0, 3)
4749

4850
def test_chains_sync_when_long_enough(self):
4951
self.log.info("Generate blocks on the node with no required chainwork, and verify nodes 1 and 2 have no new headers in their headers tree")
5052
with self.nodes[1].assert_debug_log(expected_msgs=["[net] Ignoring low-work chain (height=14)"]), self.nodes[2].assert_debug_log(expected_msgs=["[net] Ignoring low-work chain (height=14)"]):
5153
self.generate(self.nodes[0], NODE1_BLOCKS_REQUIRED-1, sync_fun=self.no_op)
5254

53-
for node in self.nodes[1:]:
55+
# Node3 should always allow headers due to noban permissions
56+
self.log.info("Check that node3 will sync headers (due to noban permissions)")
57+
58+
def check_node3_chaintips(num_tips, tip_hash, height):
59+
node3_chaintips = self.nodes[3].getchaintips()
60+
assert(len(node3_chaintips) == num_tips)
61+
assert {
62+
'height': height,
63+
'hash': tip_hash,
64+
'branchlen': height,
65+
'status': 'headers-only',
66+
} in node3_chaintips
67+
68+
check_node3_chaintips(2, self.nodes[0].getbestblockhash(), NODE1_BLOCKS_REQUIRED-1)
69+
70+
for node in self.nodes[1:3]:
5471
chaintips = node.getchaintips()
5572
assert(len(chaintips) == 1)
5673
assert {
@@ -63,7 +80,7 @@ def test_chains_sync_when_long_enough(self):
6380
self.log.info("Generate more blocks to satisfy node1's minchainwork requirement, and verify node2 still has no new headers in headers tree")
6481
with self.nodes[2].assert_debug_log(expected_msgs=["[net] Ignoring low-work chain (height=15)"]):
6582
self.generate(self.nodes[0], NODE1_BLOCKS_REQUIRED - self.nodes[0].getblockcount(), sync_fun=self.no_op)
66-
self.sync_blocks(self.nodes[0:2])
83+
self.sync_blocks(self.nodes[0:2]) # node3 will sync headers (noban permissions) but not blocks (due to minchainwork)
6784

6885
assert {
6986
'height': 0,
@@ -74,10 +91,13 @@ def test_chains_sync_when_long_enough(self):
7491

7592
assert(len(self.nodes[2].getchaintips()) == 1)
7693

77-
self.log.info("Generate long chain for node0/node1")
94+
self.log.info("Check that node3 accepted these headers as well")
95+
check_node3_chaintips(2, self.nodes[0].getbestblockhash(), NODE1_BLOCKS_REQUIRED)
96+
97+
self.log.info("Generate long chain for node0/node1/node3")
7898
self.generate(self.nodes[0], NODE2_BLOCKS_REQUIRED-self.nodes[0].getblockcount(), sync_fun=self.no_op)
7999

80-
self.log.info("Verify that node2 will sync the chain when it gets long enough")
100+
self.log.info("Verify that node2 and node3 will sync the chain when it gets long enough")
81101
self.sync_blocks()
82102

83103
def test_peerinfo_includes_headers_presync_height(self):

0 commit comments

Comments
 (0)