Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc-invalid-message.py
- This file was added.
Property | Old Value | New Value |
---|---|---|
File Mode | null | 100755 |
#!/usr/bin/env python3 | |||||
# Copyright (c) 2019 The Bitcoin developers | |||||
# Distributed under the MIT software license, see the accompanying | |||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
"""ABC Invalid Message Test | |||||
Test that invalid messages get rejected and/or ban the sender as expected for | |||||
each case. | |||||
""" | |||||
import struct | |||||
from test_framework.blocktools import create_block, create_coinbase | |||||
from test_framework.mininode import ( | |||||
NetworkThread, | |||||
NodeConn, | |||||
NodeConnCB, | |||||
msg_block, | |||||
) | |||||
from test_framework.test_framework import BitcoinTestFramework | |||||
from test_framework.util import p2p_port, wait_until | |||||
def msg_bad_checksum(connection, original_message): | |||||
message_data = bytearray(connection.format_message(original_message)) | |||||
command = original_message.command | |||||
data = original_message.serialize() | |||||
i = 0 | |||||
i += len(connection.MAGIC_BYTES[connection.network]) | |||||
i += len(command) | |||||
i += len(b"\x00" * (12 - len(command))) | |||||
i += len(struct.pack("<I", len(data))) | |||||
# Make the checksum invalid | |||||
message_data[i] = ~message_data[i] & 0xFF | |||||
deadalnix: Use a xor or something, because this may not invalid the checksum | |||||
return message_data | |||||
class InvalidMessageTest(BitcoinTestFramework): | |||||
def set_test_params(self): | |||||
self.setup_clean_chain = False | |||||
self.num_nodes = 2 | |||||
deadalnixUnsubmitted Done Inline ActionsYou don't need two nodes. deadalnix: You don't need two nodes. | |||||
def run_test(self): | |||||
# Create a P2P connection to one of the nodes | |||||
callbacks = [NodeConnCB(), NodeConnCB()] | |||||
connections = [] | |||||
for i in range(len(callbacks)): | |||||
connections.append( | |||||
NodeConn('127.0.0.1', p2p_port(i), self.nodes[i], callbacks[i])) | |||||
callbacks[i].add_connection(connections[i]) | |||||
NetworkThread().start() | |||||
for c in callbacks: | |||||
c.wait_for_verack() | |||||
# Create a valid block message | |||||
block_hash = self.nodes[0].getbestblockhash() | |||||
tip = int(block_hash, 16) | |||||
height = self.nodes[0].getblockcount() | |||||
block_time = self.nodes[0].getblock(block_hash)['time'] | |||||
block = create_block(tip, create_coinbase(height + 1), block_time + 1) | |||||
block.solve() | |||||
valid_message = msg_block(block) | |||||
deadalnixUnsubmitted Done Inline ActionsYou should use a very simple message like ping, inv or sedheaders, and certainly avoid something that is very stateful. deadalnix: You should use a very simple message like ping, inv or sedheaders, and certainly avoid… | |||||
def wait_for_tip(node, tip): | |||||
def check_tip(): | |||||
return node.getbestblockhash() == tip | |||||
wait_until(check_tip) | |||||
# The valid message is accepted by node 0 | |||||
callbacks[0].send_message(valid_message) | |||||
wait_for_tip(self.nodes[0], block.hash) | |||||
print(self.nodes[0].getbestblockhash()) | |||||
deadalnixUnsubmitted Done Inline ActionsRemove deadalnix: Remove | |||||
# Make an invalid copy of the valid message with an invalid checksum | |||||
invalid_message = msg_bad_checksum(connections[1], valid_message) | |||||
# The invalid message should cause a disconnect from node 1 because we | |||||
# are now banned | |||||
callbacks[1].send_raw_message(invalid_message) | |||||
callbacks[1].wait_for_disconnect() | |||||
if __name__ == '__main__': | |||||
InvalidMessageTest().main() |
Use a xor or something, because this may not invalid the checksum