diff options
-rw-r--r-- | src/net_processing.cpp | 7 | ||||
-rwxr-xr-x | test/functional/p2p_headers_sync_with_minchainwork.py | 32 |
2 files changed, 33 insertions, 6 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 746e3bedde..74700580ad 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2820,6 +2820,13 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer, } } + // If our peer has NetPermissionFlags::NoBan privileges, then bypass our + // anti-DoS logic (this saves bandwidth when we connect to a trusted peer + // on startup). + if (pfrom.HasPermission(NetPermissionFlags::NoBan)) { + already_validated_work = true; + } + // At this point, the headers connect to something in our block index. // Do anti-DoS checks to determine if we should process or store for later // processing. diff --git a/test/functional/p2p_headers_sync_with_minchainwork.py b/test/functional/p2p_headers_sync_with_minchainwork.py index 6e17525c28..016375222d 100755 --- a/test/functional/p2p_headers_sync_with_minchainwork.py +++ b/test/functional/p2p_headers_sync_with_minchainwork.py @@ -28,9 +28,9 @@ NODE2_BLOCKS_REQUIRED = 2047 class RejectLowDifficultyHeadersTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True - self.num_nodes = 3 + self.num_nodes = 4 # Node0 has no required chainwork; node1 requires 15 blocks on top of the genesis block; node2 requires 2047 - self.extra_args = [["-minimumchainwork=0x0", "-checkblockindex=0"], ["-minimumchainwork=0x1f", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0"]] + self.extra_args = [["-minimumchainwork=0x0", "-checkblockindex=0"], ["-minimumchainwork=0x1f", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0"], ["-minimumchainwork=0x1000", "-checkblockindex=0", "-whitelist=noban@127.0.0.1"]] def setup_network(self): self.setup_nodes() @@ -40,17 +40,34 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): def disconnect_all(self): self.disconnect_nodes(0, 1) self.disconnect_nodes(0, 2) + self.disconnect_nodes(0, 3) def reconnect_all(self): self.connect_nodes(0, 1) self.connect_nodes(0, 2) + self.connect_nodes(0, 3) def test_chains_sync_when_long_enough(self): 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") 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)"]): self.generate(self.nodes[0], NODE1_BLOCKS_REQUIRED-1, sync_fun=self.no_op) - for node in self.nodes[1:]: + # Node3 should always allow headers due to noban permissions + self.log.info("Check that node3 will sync headers (due to noban permissions)") + + def check_node3_chaintips(num_tips, tip_hash, height): + node3_chaintips = self.nodes[3].getchaintips() + assert(len(node3_chaintips) == num_tips) + assert { + 'height': height, + 'hash': tip_hash, + 'branchlen': height, + 'status': 'headers-only', + } in node3_chaintips + + check_node3_chaintips(2, self.nodes[0].getbestblockhash(), NODE1_BLOCKS_REQUIRED-1) + + for node in self.nodes[1:3]: chaintips = node.getchaintips() assert(len(chaintips) == 1) assert { @@ -63,7 +80,7 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): self.log.info("Generate more blocks to satisfy node1's minchainwork requirement, and verify node2 still has no new headers in headers tree") with self.nodes[2].assert_debug_log(expected_msgs=["[net] Ignoring low-work chain (height=15)"]): self.generate(self.nodes[0], NODE1_BLOCKS_REQUIRED - self.nodes[0].getblockcount(), sync_fun=self.no_op) - self.sync_blocks(self.nodes[0:2]) + self.sync_blocks(self.nodes[0:2]) # node3 will sync headers (noban permissions) but not blocks (due to minchainwork) assert { 'height': 0, @@ -74,10 +91,13 @@ class RejectLowDifficultyHeadersTest(BitcoinTestFramework): assert(len(self.nodes[2].getchaintips()) == 1) - self.log.info("Generate long chain for node0/node1") + self.log.info("Check that node3 accepted these headers as well") + check_node3_chaintips(2, self.nodes[0].getbestblockhash(), NODE1_BLOCKS_REQUIRED) + + self.log.info("Generate long chain for node0/node1/node3") self.generate(self.nodes[0], NODE2_BLOCKS_REQUIRED-self.nodes[0].getblockcount(), sync_fun=self.no_op) - self.log.info("Verify that node2 will sync the chain when it gets long enough") + self.log.info("Verify that node2 and node3 will sync the chain when it gets long enough") self.sync_blocks() def test_peerinfo_includes_headers_presync_height(self): |