def test_key_message(self): block_hash = Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) network_num = 12345 key = helpers.generate_bytes(crypto.KEY_SIZE) self._test_to_old_version_broadcast_message(KeyMessage(message_hash=block_hash, network_num=network_num, source_id=NEW_VERSION_SOURCE_ID, key=key)) self._test_to_new_version_broadcast_message(KeyMessageV4(msg_hash=block_hash, network_num=network_num, key=key))
def test_broadcast_message(self): block_hash = Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) blob = helpers.generate_bytes(250) network_num = 1234 self._test_to_old_version_broadcast_message(BroadcastMessage(network_num=network_num, message_hash=block_hash, source_id=NEW_VERSION_SOURCE_ID, blob=blob)) self._test_to_new_version_broadcast_message(BroadcastMessageV4(network_num=network_num, msg_hash=block_hash, blob=blob))
def test_tx_message(self): tx_hash = Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) tx_contents = helpers.generate_bytes(250) network_num = 1234 self._test_to_old_version_broadcast_message(TxMessage(message_hash=tx_hash, network_num=network_num, source_id=NEW_VERSION_SOURCE_ID, tx_val=tx_contents)) self._test_to_new_version_broadcast_message(TxMessageV4(tx_hash=tx_hash, network_num=network_num, tx_val=tx_contents))
def test_get_receipts_eth_message(self): self._test_msg_serialization( GetReceiptsEthProtocolMessage, False, # passing randomly generated hashes [ helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN) ])
def get_dummy_block_header( nonce, timestamp=None, block_number=None, prev_block_hash: Optional[Sha256Hash] = None) -> BlockHeader: if timestamp is None: timestamp = 5 * nonce if block_number is None: block_number = 2 * nonce if prev_block_hash is None: prev_block_hash = helpers.generate_bytes( eth_common_constants.BLOCK_HASH_LEN) else: prev_block_hash = prev_block_hash.binary # create BlockHeader object with dummy values multiplied by nonce to be able generate txs with different value return BlockHeader( prev_block_hash, helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.ADDRESS_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), 100 * nonce, nonce, block_number, 3 * nonce, 4 * nonce, timestamp, helpers.generate_bytes(100 * nonce), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(nonce))
def get_dummy_transaction(nonce: int, gas_price: Optional[int] = None, v: int = 27, to_address_str: Optional[str] = None) -> Transaction: if gas_price is None: gas_price = 2 * nonce if to_address_str is None: to_address = helpers.generate_bytes(eth_common_constants.ADDRESS_LEN) else: to_address = convert.hex_to_bytes(to_address_str) # create transaction object with dummy values multiplied by nonce to be able generate txs with different values return Transaction(nonce, gas_price, 3 * nonce, to_address, 4 * nonce, helpers.generate_bytes(15 * nonce), v, 6 * nonce, 7 * nonce)
def get_dummy_access_list_transaction( nonce: int, gas_price: Optional[int] = None, v: int = 27, to_address_str: Optional[str] = None) -> Transaction: if gas_price is None: gas_price = 2 * nonce if to_address_str is None: to_address = helpers.generate_bytes(eth_common_constants.ADDRESS_LEN) else: to_address = convert.hex_to_bytes(to_address_str) return AccessListTransaction(8 * nonce, nonce, gas_price, 3 * nonce, to_address, 4 * nonce, helpers.generate_bytes(15 * nonce), [], v, 6 * nonce, 7 * nonce)
def test_broadcast_message_cut_through_to_old(self): block_hash = Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) blob = helpers.generate_bytes(250) network_num = 1234 new_message = BroadcastMessage(network_num=network_num, message_hash=block_hash, source_id=NEW_VERSION_SOURCE_ID, blob=blob) new_message_bytes = new_message.rawbytes() old_message_bytes = bloxroute_version_manager.convert_message_first_bytes_to_older_version( 5, BroadcastMessage.MESSAGE_TYPE, new_message_bytes) msg_type, payload_length = BroadcastMessageV5.unpack(old_message_bytes) old_msg = BroadcastMessageV5.initialize_class( BroadcastMessageV5, old_message_bytes, (msg_type, payload_length)) self._validate_messages_match(old_msg, new_message)
def test_new_block_hashes_eth_message(self): self._test_msg_serialization( NewBlockHashesEthProtocolMessage, False, # passing few dummy block hashes [ BlockHash( helpers.generate_bytes( eth_common_constants.BLOCK_HASH_LEN), 111), BlockHash( helpers.generate_bytes( eth_common_constants.BLOCK_HASH_LEN), 222), BlockHash( helpers.generate_bytes( eth_common_constants.BLOCK_HASH_LEN), 333) ])
def test_block_hold_message(self): block_hash = Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) network_num = 12345 self._test_to_old_version_broadcast_message(BlockHoldingMessage(block_hash=block_hash, network_num=network_num, source_id=NEW_VERSION_SOURCE_ID)) self._test_to_new_version_broadcast_message(BlockHoldingMessageV4(block_hash=block_hash, network_num=network_num))
def test_block_confirmation_msg(self): short_ids = [random.randint(0, 1000000) for _ in range(150)] tx_hashes = [ Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) for _ in range(10) ] message = BlockConfirmationMessage(self.HASH, self.NETWORK_NUM, self.NODE_ID, sids=short_ids, tx_hashes=tx_hashes) self.get_message_preview_successfully( message, BlockConfirmationMessage.MESSAGE_TYPE, SHA256_HASH_LEN * len(tx_hashes) + constants.UL_INT_SIZE_IN_BYTES * len(short_ids) + AbstractBroadcastMessage.PAYLOAD_LENGTH + constants.UL_INT_SIZE_IN_BYTES * 2) rebuilt_msg = self.create_message_successfully( message, BlockConfirmationMessage) self.assertEqual(self.HASH, rebuilt_msg.block_hash()) self.assertEqual(short_ids, rebuilt_msg.short_ids()) self.assertEqual(tx_hashes, rebuilt_msg.transaction_hashes()) self.assertEqual(self.NETWORK_NUM, rebuilt_msg.network_num()) self.assertEqual(self.NODE_ID, rebuilt_msg.source_id())
async def test_connection_and_close_while_receiving_subscriptions(self): async with WsProvider(self.ws_uri) as ws: self.assertEqual(1, len(self.server._connections)) connection_handler = self.server._connections[0] self.assertTrue(ws.running) subscription_id = await ws.subscribe("newTxs") tx_contents = helpers.generate_bytes(250) raw_published_message = RawTransaction( helpers.generate_object_hash(), memoryview(tx_contents)) serialized_published_message = RawTransactionFeedEntry( raw_published_message.tx_hash, raw_published_message.tx_contents) self.gateway_node.feed_manager.publish_to_feed( "newTxs", raw_published_message) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(serialized_published_message.tx_hash, subscription_message.notification["tx_hash"]) self.assertEqual(serialized_published_message.tx_contents, subscription_message.notification["tx_contents"]) task = asyncio.create_task( ws.get_next_subscription_notification_by_id(subscription_id)) await connection_handler.close() await asyncio.sleep(0.01) exception = task.exception() self.assertIsInstance(exception, WsException)
def test_discovery_pong_eth_message(self): self._test_msg_serialization( PongEthDiscoveryMessage, True, ("192.1.2.3", 11111, 22222), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), int(time.time()), )
def _create_block_header(self, block_number: int, difficulty: int) -> BlockHeader: block_header = BlockHeader( helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.ADDRESS_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), 100, difficulty, block_number, 3, 4, 1601410624, helpers.generate_bytes(100), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(12345)) return block_header
def test_get_block_headers_eth_message(self): self._test_msg_serialization( GetBlockHeadersEthProtocolMessage, False, helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), 111, 222, 0, )
def _create_block_header_bytes(self, block_number: int, difficulty: int) -> memoryview: block_header = BlockHeader( helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(eth_common_constants.ADDRESS_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), helpers.generate_bytes(eth_common_constants.MERKLE_ROOT_LEN), 100, difficulty, block_number, 3, 4, 1601410624, helpers.generate_bytes(100), helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN), helpers.generate_bytes(12345)) block_header_bytes = rlp.encode(block_header, BlockHeader) return memoryview(block_header_bytes)
def test_broadcast_message_cut_through_from_old(self): block_hash = Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) blob = helpers.generate_bytes(250) network_num = 1234 old_message = BroadcastMessageV5(network_num=network_num, msg_hash=block_hash, blob=blob) old_message_bytes = old_message.rawbytes() new_message_bytes = bloxroute_version_manager.convert_message_first_bytes_from_older_version( 5, BroadcastMessage.MESSAGE_TYPE, old_message_bytes) new_message_bytes = bloxroute_version_manager.convert_message_last_bytes_from_older_version( 5, BroadcastMessage.MESSAGE_TYPE, new_message_bytes) msg_type, payload_length = AbstractBloxrouteMessage.unpack( new_message_bytes) new_msg = AbstractBloxrouteMessage.initialize_class( BroadcastMessage, bytearray(new_message_bytes.tobytes()), (msg_type, payload_length)) self._validate_messages_match(old_message, new_msg) self.assertEqual(EMPTY_SOURCE_ID_STR, new_msg.source_id())
def generate_eth_raw_transaction_with_to_address( source: FeedSource = FeedSource.BDN_SOCKET, to_address: str = helpers.generate_bytes(eth_common_constants.ADDRESS_LEN) ) -> EthRawTransaction: transaction = get_dummy_transaction(1, to_address_str=to_address) transactions_eth_message = TransactionsEthProtocolMessage( None, [transaction]) tx_message = EthNormalMessageConverter().tx_to_bx_txs( transactions_eth_message, 5)[0][0] return EthRawTransaction(tx_message.tx_hash(), tx_message.tx_val(), source)
def test_transaction_cleanup_msg(self): short_ids = [23, 99, 192, 1089, 3000500] tx_hashes = [ Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)), Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) ] message = TransactionCleanupMessage(self.NETWORK_NUM, self.NODE_ID, sids=short_ids, tx_hashes=tx_hashes) self.get_message_preview_successfully(message, TransactionCleanupMessage.MESSAGE_TYPE, SHA256_HASH_LEN * len(tx_hashes) + constants.UL_INT_SIZE_IN_BYTES * len(short_ids) + AbstractBroadcastMessage.PAYLOAD_LENGTH + constants.UL_INT_SIZE_IN_BYTES * 2) rebuilt_msg = self.create_message_successfully(message, TransactionCleanupMessage) self.assertEqual(short_ids, rebuilt_msg.short_ids()) self.assertEqual(tx_hashes, rebuilt_msg.transaction_hashes()) self.assertEqual(self.NETWORK_NUM, rebuilt_msg.network_num()) self.assertEqual(self.NODE_ID, rebuilt_msg.source_id()) self.assertNotEqual(NULL_SHA256_HASH, rebuilt_msg.message_hash()) print(rebuilt_msg.message_hash())
def test_tx_bx_message_setting_attributes(self): contents = helpers.generate_bytes(250) timestamp = time.time() tx_message = TxMessage(self.HASH, network_num=1, source_id=self.NODE_ID, short_id=2, tx_val=contents, transaction_flag=TransactionFlag.PAID_TX, timestamp=timestamp) tx_message.clear_protected_fields() rebuilt_tx_message = self.create_message_successfully( tx_message, TxMessage) self.assertEqual(constants.NULL_TX_SID, rebuilt_tx_message.short_id()) self.assertEqual(constants.NULL_TX_TIMESTAMP, rebuilt_tx_message.timestamp())
def test_new_block_hashes_msg_from_block_hash(self): block_hash_bytes = helpers.generate_bytes( eth_common_constants.BLOCK_HASH_LEN) block_hash = Sha256Hash(block_hash_bytes) block_number = 1000 new_block_hashes_msg_from_hash = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair( block_hash, block_number) new_block_hashes_msg_from_hash.deserialize() self.assertEqual( 1, len(new_block_hashes_msg_from_hash.get_block_hash_number_pairs())) deserialized_hash, deserialized_block_number = new_block_hashes_msg_from_hash.get_block_hash_number_pairs( )[0] self.assertEqual(deserialized_hash, block_hash) self.assertEqual(block_number, block_number)
def test_store(self): data = helpers.generate_bytes(100) ssl_certificate_factory.store(self.file_path, data, self._stream_factory) self.assertEqual(data, self.stream_mock.data)
def test_receipts_eth_message(self): self._test_msg_serialization(ReceiptsEthProtocolMessage, False, helpers.generate_bytes(1000))
def test_node_data_eth_message(self): self._test_msg_serialization(NodeDataEthProtocolMessage, False, helpers.generate_bytes(1000))
def test_txs_message(self): tx_hash = Sha256Hash(helpers.generate_bytes(crypto.SHA256_HASH_LEN)) tx_contents = helpers.generate_bytes(250) self._test_to_old_version(TxsMessage([TransactionInfo(tx_hash, tx_contents, 1)])) self._test_to_new_version(TxsMessageV4([TransactionInfo(tx_hash, tx_contents, 1)]))
def notify_message(self) -> NotificationMessage: return NotificationMessage(NotificationCode.QUOTA_FILL_STATUS, str(helpers.generate_bytes(100)))
class BlockchainSyncEthTest(AbstractRLPxCipherTest): BLOCK_HASH = helpers.generate_bytes(eth_common_constants.BLOCK_HASH_LEN) def setUp(self): self.local_node_fileno = 1 self.local_node_fileno_2 = 2 self.remote_node_fileno = 3 self.local_blockchain_ip = "127.0.0.1" self.local_blockchain_port = 30303 self.local_blockchain_port_2 = 30302 eth_node_private_key = crypto_utils.make_private_key(helpers.generate_bytearray(111)) self.gateway_node = spies.make_spy_node( EthGatewayNode, 8000, include_default_eth_args=True, blockchain_protocol="Ethereum", blockchain_address=(self.local_blockchain_ip, self.local_blockchain_port), blockchain_peers="enode://d76d7d11a822fab02836f8b0ea462205916253eb630935d15191fb6f9d218cd94a768fc5b3d5516b9ed5010a4765f95aea7124a39d0ab8aaf6fa3d57e21ef396@127.0.0.1:30302", pub_key="d76d7d11a822fab02836f8b0ea462205916253eb630935d15191fb6f9d218cd94a768fc5b3d5516b9ed5010a4765f95aea7124a39d0ab8aaf6fa3d57e21ef396") gateway_node_private_key = convert.hex_to_bytes(self.gateway_node.opts.private_key) eth_node_public_key = crypto_utils.private_to_public_key(eth_node_private_key) self.eth_node_cipher, gateway_cipher = self.setup_ciphers(eth_node_private_key, gateway_node_private_key) self.gateway_node._node_public_key = eth_node_public_key self.gateway_node._remote_public_key = eth_node_public_key self.eth_node_connection = spies.make_spy_connection(EthNodeConnection, self.local_node_fileno, self.local_blockchain_port, self.gateway_node) self.eth_node_connection_2 = spies.make_spy_connection(EthNodeConnection, self.local_node_fileno_2, self.local_blockchain_port_2, self.gateway_node) self.eth_remote_node_connection = spies.make_spy_connection(EthRemoteConnection, self.remote_node_fileno, 8003, self.gateway_node) self.eth_node_connection._rlpx_cipher = gateway_cipher self.eth_node_connection_2._rlpx_cipher = gateway_cipher self.eth_node_connection.message_factory = EthProtocolMessageFactory(gateway_cipher) self.eth_node_connection_2.message_factory = EthProtocolMessageFactory(gateway_cipher) self.eth_remote_node_connection._rlpx_cipher = gateway_cipher self.eth_remote_node_connection.message_factory = EthProtocolMessageFactory(gateway_cipher) self.gateway_node.remote_node_conn = self.eth_remote_node_connection self.gateway_node.connection_pool.add( self.local_node_fileno, LOCALHOST, self.local_blockchain_port, self.eth_node_connection ) self.gateway_node.connection_pool.add( self.local_node_fileno_2, LOCALHOST, self.local_blockchain_port_2, self.eth_node_connection_2 ) self.gateway_node.connection_pool.add(self.remote_node_fileno, LOCALHOST, 8003, self.eth_remote_node_connection) def test_block_headers_request(self): get_headers = GetBlockHeadersEthProtocolMessage(None, self.BLOCK_HASH, 111, 222, 0) # Reply with empty headers to the first get headers request for fast sync mode support get_headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(get_headers.msg_type, get_headers.rawbytes())) for get_headers_frame in get_headers_frames: helpers.receive_node_message(self.gateway_node, self.local_node_fileno, get_headers_frame) self.eth_remote_node_connection.enqueue_msg.assert_not_called() self.eth_node_connection.enqueue_msg.assert_called_once_with(BlockHeadersEthProtocolMessage(None, [])) # The second get headers message should be proxied to remote blockchain node get_headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(get_headers.msg_type, get_headers.rawbytes())) for get_headers_frame in get_headers_frames: helpers.receive_node_message(self.gateway_node, self.local_node_fileno, get_headers_frame) self.eth_remote_node_connection.enqueue_msg.assert_called_once_with(get_headers) headers = BlockHeadersEthProtocolMessage(None, [ mock_eth_messages.get_dummy_block_header(1), mock_eth_messages.get_dummy_block_header(2) ]) headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(headers.msg_type, headers.rawbytes())) for headers_frame in headers_frames: helpers.receive_node_message(self.gateway_node, self.remote_node_fileno, headers_frame) self.eth_node_connection.enqueue_msg.assert_called_with(headers) def test_queued_block_headers_requests_from_different_nodes(self): get_headers = GetBlockHeadersEthProtocolMessage(None, self.BLOCK_HASH, 111, 222, 0) # Reply with empty headers to the first get headers request for fast sync mode support get_headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(get_headers.msg_type, get_headers.rawbytes())) for get_headers_frame in get_headers_frames: helpers.receive_node_message(self.gateway_node, self.local_node_fileno, get_headers_frame) self.eth_remote_node_connection.enqueue_msg.assert_not_called() self.eth_node_connection.enqueue_msg.assert_called_once_with(BlockHeadersEthProtocolMessage(None, [])) # Reply with empty headers to second blockchain node get_headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(get_headers.msg_type, get_headers.rawbytes())) for get_headers_frame in get_headers_frames: helpers.receive_node_message(self.gateway_node, self.local_node_fileno_2, get_headers_frame) self.eth_remote_node_connection.enqueue_msg.assert_not_called() self.eth_node_connection_2.enqueue_msg.assert_called_once_with(BlockHeadersEthProtocolMessage(None, [])) # The second get headers message should be proxied to remote blockchain node get_headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(get_headers.msg_type, get_headers.rawbytes())) for get_headers_frame in get_headers_frames: helpers.receive_node_message(self.gateway_node, self.local_node_fileno, get_headers_frame) self.eth_remote_node_connection.enqueue_msg.assert_called_once_with(get_headers) # request from second blockchain node self.eth_remote_node_connection.enqueue_msg.reset_mock() get_headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(get_headers.msg_type, get_headers.rawbytes())) for get_headers_frame in get_headers_frames: helpers.receive_node_message(self.gateway_node, self.local_node_fileno_2, get_headers_frame) self.eth_remote_node_connection.enqueue_msg.assert_called_once_with(get_headers) # response for first blockchain node headers = BlockHeadersEthProtocolMessage(None, [ mock_eth_messages.get_dummy_block_header(1), mock_eth_messages.get_dummy_block_header(2) ]) headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(headers.msg_type, headers.rawbytes())) for headers_frame in headers_frames: helpers.receive_node_message(self.gateway_node, self.remote_node_fileno, headers_frame) self.eth_node_connection.enqueue_msg.assert_called_with(headers) # receive response for second blockchain node headers = BlockHeadersEthProtocolMessage(None, [ mock_eth_messages.get_dummy_block_header(1), mock_eth_messages.get_dummy_block_header(2) ]) headers_frames = map(self.eth_node_cipher.encrypt_frame, frame_utils.get_frames(headers.msg_type, headers.rawbytes())) for headers_frame in headers_frames: helpers.receive_node_message(self.gateway_node, self.remote_node_fileno, headers_frame) self.eth_node_connection_2.enqueue_msg.assert_called_with(headers)
def get_dummy_transaction(nonce: int, v: int = 27) -> Transaction: # create transaction object with dummy values multiplied by nonce to be able generate txs with different values return Transaction( nonce, 2 * nonce, 3 * nonce, helpers.generate_bytes(eth_common_constants.ADDRESS_LEN), 4 * nonce, helpers.generate_bytes(15 * nonce), v, 6 * nonce, 7 * nonce)