Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc-invalid-message.py
Show All 24 Lines | def msg_bad_checksum(connection, original_message): | ||||
i += len(struct.pack("<I", len(data))) | i += len(struct.pack("<I", len(data))) | ||||
# Make the checksum invalid | # Make the checksum invalid | ||||
message_data[i] = message_data[i] ^ 0xAA | message_data[i] = message_data[i] ^ 0xAA | ||||
return message_data | return message_data | ||||
class BadVersionP2PInterface(P2PInterface): | class BadVersionP2PInterface(P2PInterface): | ||||
def peer_connect(self, *args, services=NODE_NETWORK, | def peer_connect(self, *args, services=NODE_NETWORK, send_version=False, **kwargs): | ||||
send_version=False, **kwargs): | |||||
self.services = services | self.services = services | ||||
return super().peer_connect(*args, send_version=send_version, **kwargs) | return super().peer_connect(*args, send_version=send_version, **kwargs) | ||||
def send_version(self): | def send_version(self): | ||||
# Send version message with invalid checksum | # Send version message with invalid checksum | ||||
vt = msg_version() | vt = msg_version() | ||||
vt.nServices = self.services | vt.nServices = self.services | ||||
vt.addrTo.ip = self.dstaddr | vt.addrTo.ip = self.dstaddr | ||||
Show All 11 Lines | class InvalidMessageTest(BitcoinTestFramework): | ||||
def run_test(self): | def run_test(self): | ||||
# Try to connect to a node using an invalid checksum on version message. | # Try to connect to a node using an invalid checksum on version message. | ||||
# The version message is delayed because add_p2p_connection checks that | # The version message is delayed because add_p2p_connection checks that | ||||
# the connection is established, and sending a bad version immedately | # the connection is established, and sending a bad version immedately | ||||
# on the first connection might get our peer disconnected before the | # on the first connection might get our peer disconnected before the | ||||
# check happened, causing the test to fail. | # check happened, causing the test to fail. | ||||
bad_interface = BadVersionP2PInterface() | bad_interface = BadVersionP2PInterface() | ||||
self.nodes[0].add_p2p_connection( | self.nodes[0].add_p2p_connection( | ||||
bad_interface, send_version=False, wait_for_verack=False) | bad_interface, send_version=False, wait_for_verack=False | ||||
) | |||||
# Also connect to a node with a valid version message | # Also connect to a node with a valid version message | ||||
interface = P2PInterface() | interface = P2PInterface() | ||||
# Node with valid version message should connect successfully | # Node with valid version message should connect successfully | ||||
connection = self.nodes[1].add_p2p_connection(interface) | connection = self.nodes[1].add_p2p_connection(interface) | ||||
self.log.info( | self.log.info("Send an invalid version message and check we get banned") | ||||
"Send an invalid version message and check we get banned") | |||||
bad_interface.send_version() | bad_interface.send_version() | ||||
bad_interface.wait_for_disconnect() | bad_interface.wait_for_disconnect() | ||||
# Create a valid message | # Create a valid message | ||||
valid_message = msg_ping(interface.ping_counter) | valid_message = msg_ping(interface.ping_counter) | ||||
def wait_for_ping(): | def wait_for_ping(): | ||||
def check_ping(): | def check_ping(): | ||||
if not interface.last_message.get("pong"): | if not interface.last_message.get("pong"): | ||||
return False | return False | ||||
return interface.last_message["pong"].nonce == interface.ping_counter | return interface.last_message["pong"].nonce == interface.ping_counter | ||||
interface.wait_until(check_ping) | interface.wait_until(check_ping) | ||||
interface.ping_counter += 1 | interface.ping_counter += 1 | ||||
# The valid message is accepted | # The valid message is accepted | ||||
connection.send_message(valid_message) | connection.send_message(valid_message) | ||||
wait_for_ping() | wait_for_ping() | ||||
# Make an invalid copy of the valid message with an invalid checksum | # Make an invalid copy of the valid message with an invalid checksum | ||||
invalid_message = msg_bad_checksum(connection, valid_message) | invalid_message = msg_bad_checksum(connection, valid_message) | ||||
# The invalid message should cause a disconnect because we are now | # The invalid message should cause a disconnect because we are now | ||||
# banned | # banned | ||||
connection.send_raw_message(invalid_message) | connection.send_raw_message(invalid_message) | ||||
interface.wait_for_disconnect() | interface.wait_for_disconnect() | ||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
InvalidMessageTest().main() | InvalidMessageTest().main() |