Changeset View
Changeset View
Standalone View
Standalone View
test/functional/p2p_invalid_messages.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2015-2019 The Bitcoin Core developers | # Copyright (c) 2015-2019 The Bitcoin Core developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test node responses to invalid network messages.""" | """Test node responses to invalid network messages.""" | ||||
import asyncio | |||||
import struct | import struct | ||||
import time | import time | ||||
from test_framework.messages import ( | from test_framework.messages import ( | ||||
CBlockHeader, | CBlockHeader, | ||||
CInv, | CInv, | ||||
msg_avahello, | msg_avahello, | ||||
msg_avapoll, | msg_avapoll, | ||||
msg_avaresponse, | msg_avaresponse, | ||||
msg_getdata, | msg_getdata, | ||||
msg_headers, | msg_headers, | ||||
msg_inv, | msg_inv, | ||||
msg_ping, | |||||
MSG_TX, | MSG_TX, | ||||
ser_string, | ser_string, | ||||
) | ) | ||||
from test_framework.mininode import ( | from test_framework.mininode import ( | ||||
NetworkThread, | |||||
P2PDataStore, | P2PDataStore, | ||||
P2PInterface, | P2PInterface, | ||||
) | ) | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import hex_str_to_bytes | from test_framework.util import hex_str_to_bytes | ||||
MSG_LIMIT = 2 * 1024 * 1024 # 2MB, per MAX_PROTOCOL_MESSAGE_LENGTH | MSG_LIMIT = 2 * 1024 * 1024 # 2MB, per MAX_PROTOCOL_MESSAGE_LENGTH | ||||
VALID_DATA_LIMIT = MSG_LIMIT - 5 # Account for the 5-byte length prefix | VALID_DATA_LIMIT = MSG_LIMIT - 5 # Account for the 5-byte length prefix | ||||
Show All 34 Lines | def run_test(self): | ||||
self.test_addrv2_too_long_address() | self.test_addrv2_too_long_address() | ||||
self.test_addrv2_unrecognized_network() | self.test_addrv2_unrecognized_network() | ||||
self.test_large_inv() | self.test_large_inv() | ||||
self.test_unsolicited_ava_messages() | self.test_unsolicited_ava_messages() | ||||
self.test_resource_exhaustion() | self.test_resource_exhaustion() | ||||
def test_magic_bytes(self): | def test_magic_bytes(self): | ||||
conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | ||||
with self.nodes[0].assert_debug_log(['PROCESSMESSAGE: INVALID MESSAGESTART badmsg']): | |||||
async def swap_magic_bytes(): | msg = conn.build_message(msg_unrecognized(str_data="d")) | ||||
# Need to ignore all incoming messages from now, since they come | # modify magic bytes | ||||
# with "invalid" magic bytes | msg = b'\xff' * 4 + msg[4:] | ||||
conn._on_data = lambda: None | conn.send_raw_message(msg) | ||||
conn.magic_bytes = b'\x00\x11\x22\x32' | |||||
# Call .result() to block until the atomic swap is complete, otherwise | |||||
# we might run into races later on | |||||
asyncio.run_coroutine_threadsafe( | |||||
swap_magic_bytes(), | |||||
NetworkThread.network_event_loop).result() | |||||
with self.nodes[0].assert_debug_log(['PROCESSMESSAGE: INVALID MESSAGESTART ping']): | |||||
conn.send_message(msg_ping(nonce=0xff)) | |||||
conn.wait_for_disconnect(timeout=1) | conn.wait_for_disconnect(timeout=1) | ||||
self.nodes[0].disconnect_p2ps() | self.nodes[0].disconnect_p2ps() | ||||
def test_checksum(self): | def test_checksum(self): | ||||
conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | ||||
with self.nodes[0].assert_debug_log(['CHECKSUM ERROR (badmsg, 2 bytes), expected 78df0a04 was ffffffff']): | with self.nodes[0].assert_debug_log(['CHECKSUM ERROR (badmsg, 2 bytes), expected 78df0a04 was ffffffff']): | ||||
msg = conn.build_message(msg_unrecognized(str_data="d")) | msg = conn.build_message(msg_unrecognized(str_data="d")) | ||||
cut_len = ( | # Checksum is after start bytes (4B), message type (12B), len (4B) | ||||
# magic | cut_len = 4 + 12 + 4 | ||||
4 + | |||||
# msgtype | |||||
12 + | |||||
# len | |||||
4 | |||||
) | |||||
# modify checksum | # modify checksum | ||||
msg = msg[:cut_len] + b'\xff' * 4 + msg[cut_len + 4:] | msg = msg[:cut_len] + b'\xff' * 4 + msg[cut_len + 4:] | ||||
self.nodes[0].p2p.send_raw_message(msg) | self.nodes[0].p2p.send_raw_message(msg) | ||||
conn.wait_for_disconnect() | conn.wait_for_disconnect() | ||||
self.nodes[0].disconnect_p2ps() | self.nodes[0].disconnect_p2ps() | ||||
def test_size(self): | def test_size(self): | ||||
conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | ||||
▲ Show 20 Lines • Show All 184 Lines • Show Last 20 Lines |