Skip to content

Commit 576e16e

Browse files
committed
Merge bitcoin/bitcoin#26184: test: p2p: check that headers message with invalid proof-of-work disconnects peer
7726712 test: p2p: check that headers message with invalid proof-of-work disconnects peer (Sebastian Falbesoner) Pull request description: One of the earliest anti-DoS checks done after receiving and deserializing a `headers` message from a peer is verifying whether the proof-of-work is valid (called in method `PeerManagerImpl::ProcessHeadersMessage`): https://github.com/bitcoin/bitcoin/blob/f227e153e80c8c50c30d76e1ac638d7206c7ff61/src/net_processing.cpp#L2752-L2762 The called method `PeerManagerImpl::CheckHeadersPoW` calls `Misbehaving` with a score of 100, i.e. leading to an immediate disconnect of the peer: https://github.com/bitcoin/bitcoin/blob/f227e153e80c8c50c30d76e1ac638d7206c7ff61/src/net_processing.cpp#L2368-L2372 This PR adds a simple test for both the misbehaving log and the resulting disconnect. For creating a block header with invalid proof-of-work, we first create one that is accepted by the node (the difficulty field `nBits` is copied from the genesis block) and based on that the nonce is modified until we have block header hash prefix that is too high to fulfill even the minimum difficulty. ACKs for top commit: Sjors: ACK 7726712 achow101: ACK 7726712 brunoerg: crACK 7726712 furszy: Code review ACK 7726712 with a non-blocking speedup. Tree-SHA512: 680aa7939158d1dc672b90aa6554ba2b3a92584b6d3bcb0227776035858429feb8bc66eed18b47de0fe56df7d9b3ddaee231aaeaa360136603b9ad4b19e6ac11
2 parents fb2f093 + 7726712 commit 576e16e

File tree

1 file changed

+33
-1
lines changed

1 file changed

+33
-1
lines changed

test/functional/p2p_invalid_messages.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
MAX_HEADERS_RESULTS,
1414
MAX_INV_SIZE,
1515
MAX_PROTOCOL_MESSAGE_LENGTH,
16+
MSG_TX,
17+
from_hex,
1618
msg_getdata,
1719
msg_headers,
1820
msg_inv,
1921
msg_ping,
20-
MSG_TX,
2122
msg_version,
2223
ser_string,
2324
)
@@ -73,6 +74,7 @@ def run_test(self):
7374
self.test_oversized_inv_msg()
7475
self.test_oversized_getdata_msg()
7576
self.test_oversized_headers_msg()
77+
self.test_invalid_pow_headers_msg()
7678
self.test_resource_exhaustion()
7779

7880
def test_buffer(self):
@@ -248,6 +250,36 @@ def test_oversized_headers_msg(self):
248250
size = MAX_HEADERS_RESULTS + 1
249251
self.test_oversized_msg(msg_headers([CBlockHeader()] * size), size)
250252

253+
def test_invalid_pow_headers_msg(self):
254+
self.log.info("Test headers message with invalid proof-of-work is logged as misbehaving and disconnects peer")
255+
blockheader_tip_hash = self.nodes[0].getbestblockhash()
256+
blockheader_tip = from_hex(CBlockHeader(), self.nodes[0].getblockheader(blockheader_tip_hash, False))
257+
258+
# send valid headers message first
259+
assert_equal(self.nodes[0].getblockchaininfo()['headers'], 0)
260+
blockheader = CBlockHeader()
261+
blockheader.hashPrevBlock = int(blockheader_tip_hash, 16)
262+
blockheader.nTime = int(time.time())
263+
blockheader.nBits = blockheader_tip.nBits
264+
blockheader.rehash()
265+
while not blockheader.hash.startswith('0'):
266+
blockheader.nNonce += 1
267+
blockheader.rehash()
268+
peer = self.nodes[0].add_p2p_connection(P2PInterface())
269+
peer.send_and_ping(msg_headers([blockheader]))
270+
assert_equal(self.nodes[0].getblockchaininfo()['headers'], 1)
271+
chaintips = self.nodes[0].getchaintips()
272+
assert_equal(chaintips[0]['status'], 'headers-only')
273+
assert_equal(chaintips[0]['hash'], blockheader.hash)
274+
275+
# invalidate PoW
276+
while not blockheader.hash.startswith('f'):
277+
blockheader.nNonce += 1
278+
blockheader.rehash()
279+
with self.nodes[0].assert_debug_log(['Misbehaving', 'header with invalid proof of work']):
280+
peer.send_message(msg_headers([blockheader]))
281+
peer.wait_for_disconnect()
282+
251283
def test_resource_exhaustion(self):
252284
self.log.info("Test node stays up despite many large junk messages")
253285
conn = self.nodes[0].add_p2p_connection(P2PDataStore())

0 commit comments

Comments
 (0)