Changeset View
Changeset View
Standalone View
Standalone View
test/functional/p2p_invalid_messages.py
Show All 9 Lines | 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 ( | ||||
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, | |||||
assert_equal, | |||||
wait_until, | |||||
) | |||||
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 | ||||
class msg_unrecognized: | class msg_unrecognized: | ||||
"""Nonsensical message. Modeled after similar types in test_framework.messages.""" | """Nonsensical message. Modeled after similar types in test_framework.messages.""" | ||||
Show All 15 Lines | |||||
class InvalidMessagesTest(BitcoinTestFramework): | class InvalidMessagesTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
def run_test(self): | def run_test(self): | ||||
self.test_buffer() | |||||
self.test_magic_bytes() | self.test_magic_bytes() | ||||
self.test_checksum() | self.test_checksum() | ||||
self.test_size() | self.test_size() | ||||
self.test_msgtype() | self.test_msgtype() | ||||
self.test_addrv2_empty() | self.test_addrv2_empty() | ||||
self.test_addrv2_no_addresses() | self.test_addrv2_no_addresses() | ||||
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_buffer(self): | |||||
self.log.info( | |||||
"Test message with header split across two buffers, should be received") | |||||
conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | |||||
# Create valid message | |||||
msg = conn.build_message(msg_ping(nonce=12345)) | |||||
cut_pos = 12 # Chosen at an arbitrary position within the header | |||||
# Send message in two pieces | |||||
before = int(self.nodes[0].getnettotals()['totalbytesrecv']) | |||||
conn.send_raw_message(msg[:cut_pos]) | |||||
# Wait until node has processed the first half of the message | |||||
wait_until( | |||||
lambda: int( | |||||
self.nodes[0].getnettotals()['totalbytesrecv']) != before) | |||||
middle = int(self.nodes[0].getnettotals()['totalbytesrecv']) | |||||
# If this assert fails, we've hit an unlikely race | |||||
# where the test framework sent a message in between the two halves | |||||
assert_equal(middle, before + cut_pos) | |||||
conn.send_raw_message(msg[cut_pos:]) | |||||
conn.sync_with_ping(timeout=1) | |||||
self.nodes[0].disconnect_p2ps() | |||||
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']): | with self.nodes[0].assert_debug_log(['PROCESSMESSAGE: INVALID MESSAGESTART badmsg']): | ||||
msg = conn.build_message(msg_unrecognized(str_data="d")) | msg = conn.build_message(msg_unrecognized(str_data="d")) | ||||
# modify magic bytes | # modify magic bytes | ||||
msg = b'\xff' * 4 + msg[4:] | msg = b'\xff' * 4 + msg[4:] | ||||
conn.send_raw_message(msg) | conn.send_raw_message(msg) | ||||
conn.wait_for_disconnect(timeout=1) | conn.wait_for_disconnect(timeout=1) | ||||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | def test_addrv2_unrecognized_network(self): | ||||
'04' + | '04' + | ||||
# address | # address | ||||
'09' * 4 + | '09' * 4 + | ||||
# port | # port | ||||
'208d')) | '208d')) | ||||
def test_large_inv(self): | def test_large_inv(self): | ||||
conn = self.nodes[0].add_p2p_connection(P2PInterface()) | conn = self.nodes[0].add_p2p_connection(P2PInterface()) | ||||
with self.nodes[0].assert_debug_log(['Misbehaving', 'peer=8 (0 -> 20): oversized-inv: message inv size() = 50001']): | with self.nodes[0].assert_debug_log(['Misbehaving', '(0 -> 20): oversized-inv: message inv size() = 50001']): | ||||
msg = msg_inv([CInv(MSG_TX, 1)] * 50001) | msg = msg_inv([CInv(MSG_TX, 1)] * 50001) | ||||
conn.send_and_ping(msg) | conn.send_and_ping(msg) | ||||
with self.nodes[0].assert_debug_log(['Misbehaving', 'peer=8 (20 -> 40): too-many-inv: message getdata size() = 50001']): | with self.nodes[0].assert_debug_log(['Misbehaving', '(20 -> 40): too-many-inv: message getdata size() = 50001']): | ||||
msg = msg_getdata([CInv(MSG_TX, 1)] * 50001) | msg = msg_getdata([CInv(MSG_TX, 1)] * 50001) | ||||
conn.send_and_ping(msg) | conn.send_and_ping(msg) | ||||
with self.nodes[0].assert_debug_log(['Misbehaving', 'peer=8 (40 -> 60): too-many-headers: headers message size = 2001']): | with self.nodes[0].assert_debug_log(['Misbehaving', '(40 -> 60): too-many-headers: headers message size = 2001']): | ||||
msg = msg_headers([CBlockHeader()] * 2001) | msg = msg_headers([CBlockHeader()] * 2001) | ||||
conn.send_and_ping(msg) | conn.send_and_ping(msg) | ||||
self.nodes[0].disconnect_p2ps() | self.nodes[0].disconnect_p2ps() | ||||
def test_unsolicited_ava_messages(self): | def test_unsolicited_ava_messages(self): | ||||
"""Node 0 has avalanche disabled by default. If a node does not | """Node 0 has avalanche disabled by default. If a node does not | ||||
advertise the avalanche service flag, it does not expect to receive | advertise the avalanche service flag, it does not expect to receive | ||||
any avalanche related message and should consider it as spam. | any avalanche related message and should consider it as spam. | ||||
""" | """ | ||||
conn = self.nodes[0].add_p2p_connection(P2PInterface()) | conn = self.nodes[0].add_p2p_connection(P2PInterface()) | ||||
with self.nodes[0].assert_debug_log( | with self.nodes[0].assert_debug_log( | ||||
['Misbehaving', 'peer=9 (0 -> 20): unsolicited-avahello']): | ['Misbehaving', '(0 -> 20): unsolicited-avahello']): | ||||
msg = msg_avahello() | msg = msg_avahello() | ||||
conn.send_and_ping(msg) | conn.send_and_ping(msg) | ||||
with self.nodes[0].assert_debug_log( | with self.nodes[0].assert_debug_log( | ||||
['Misbehaving', 'peer=9 (20 -> 40): unsolicited-avapoll']): | ['Misbehaving', '(20 -> 40): unsolicited-avapoll']): | ||||
msg = msg_avapoll() | msg = msg_avapoll() | ||||
conn.send_and_ping(msg) | conn.send_and_ping(msg) | ||||
with self.nodes[0].assert_debug_log( | with self.nodes[0].assert_debug_log( | ||||
['Misbehaving', 'peer=9 (40 -> 60): unsolicited-avaresponse']): | ['Misbehaving', '(40 -> 60): unsolicited-avaresponse']): | ||||
msg = msg_avaresponse() | msg = msg_avaresponse() | ||||
conn.send_and_ping(msg) | conn.send_and_ping(msg) | ||||
self.nodes[0].disconnect_p2ps() | self.nodes[0].disconnect_p2ps() | ||||
def test_resource_exhaustion(self): | def test_resource_exhaustion(self): | ||||
conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | conn = self.nodes[0].add_p2p_connection(P2PDataStore()) | ||||
conn2 = self.nodes[0].add_p2p_connection(P2PDataStore()) | conn2 = self.nodes[0].add_p2p_connection(P2PDataStore()) | ||||
msg_at_size = msg_unrecognized(str_data="b" * VALID_DATA_LIMIT) | msg_at_size = msg_unrecognized(str_data="b" * VALID_DATA_LIMIT) | ||||
Show All 24 Lines |