def test_msg_broadcast_duplicate_block_with_different_short_id(self): # test scenario when first received block is compressed with unknown short ids, # but second received block is compressed with known short ids ont_block = self.ont_block() block_hash = ont_block.block_hash() transactions = self.bx_transactions() unknown_sid_transaction_service = ExtensionTransactionService(MockNode( gateway_helpers.get_gateway_opts(8999)), 0) for i, transaction in enumerate(transactions): unknown_sid_transaction_service.assign_short_id(transaction.tx_hash(), i) unknown_sid_transaction_service.set_transaction_contents(transaction.tx_hash(), transaction.tx_val()) unknown_short_id_block = bytes( self.gateway_node.message_converter.block_to_bx_block( ont_block, unknown_sid_transaction_service, True, self.gateway_node.network.min_tx_age_seconds )[0] ) unknown_key, unknown_cipher = symmetric_encrypt(unknown_short_id_block) unknown_block_hash = crypto.double_sha256(unknown_cipher) unknown_message = BroadcastMessage(Sha256Hash(unknown_block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, False, bytearray(unknown_short_id_block)) unknown_key_message = KeyMessage(Sha256Hash(unknown_block_hash), self.TEST_NETWORK_NUM, "", unknown_key) local_transaction_service = self.gateway_node.get_tx_service() for i, transaction in enumerate(transactions): local_transaction_service.assign_short_id(transaction.tx_hash(), i + 20) local_transaction_service.set_transaction_contents(transaction.tx_hash(), transaction.tx_val()) known_short_id_block = bytes( self.gateway_node.message_converter.block_to_bx_block( ont_block, local_transaction_service, True, self.gateway_node.network.min_tx_age_seconds )[0] ) known_key, known_cipher = symmetric_encrypt(known_short_id_block) known_block_hash = crypto.double_sha256(known_cipher) known_message = BroadcastMessage(Sha256Hash(known_block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, False, bytearray(known_short_id_block)) known_key_message = KeyMessage(Sha256Hash(known_block_hash), self.TEST_NETWORK_NUM, "", known_key) self.sut.msg_broadcast(unknown_message) self.sut.msg_key(unknown_key_message) self.assertEqual(1, len(self.gateway_node.block_queuing_service)) self.assertEqual(True, self.gateway_node.block_queuing_service._blocks_waiting_for_recovery[block_hash]) self.assertEqual(1, len(self.gateway_node.block_recovery_service._block_hash_to_bx_block_hashes)) self.assertNotIn(block_hash, self.gateway_node.blocks_seen.contents) self.sut.msg_broadcast(known_message) self.sut.msg_key(known_key_message) self.gateway_node_sut.msg_get_data(GetDataOntMessage(self.magic, InventoryOntType.MSG_BLOCK.value, block_hash)) self.gateway_node.broadcast.assert_called() self.assertEqual(0, len(self.gateway_node.block_queuing_service)) self.assertEqual(0, len(self.gateway_node.block_recovery_service._block_hash_to_bx_block_hashes)) self.assertIn(block_hash, self.gateway_node.blocks_seen.contents)
def test_msg_key_wait_for_broadcast(self): ont_block = self.ont_block() bx_block = self.bx_block(ont_block) key, ciphertext = symmetric_encrypt(bx_block) block_hash = crypto.double_sha256(ciphertext) self.gateway_node.broadcast.assert_not_called() key_message = KeyMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", key) self.sut.msg_key(key_message) # handle duplicate broadcasts self.sut.msg_key(key_message) self.sut.msg_key(key_message) self.assertEqual(1, len(self.gateway_node.in_progress_blocks)) broadcast_message = BroadcastMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, True, ciphertext) self.sut.msg_broadcast(broadcast_message) self._assert_block_sent(ont_block)
def test_msg_broadcast_wait_for_key(self): ont_block = self.ont_block() bx_block = self.bx_block(ont_block) key, ciphertext = symmetric_encrypt(bx_block) block_hash = crypto.double_sha256(ciphertext) broadcast_message = BroadcastMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", BroadcastMessageType.BLOCK, True, ciphertext) self.sut.msg_broadcast(broadcast_message) # handle duplicate messages self.sut.msg_broadcast(broadcast_message) self.sut.msg_broadcast(broadcast_message) self.assertEqual(3, len(self.gateway_node.broadcast.call_args_list)) for call, conn_type in self.gateway_node.broadcast.call_args_list: msg, conn = call self.assertTrue(isinstance(msg, BlockReceivedMessage)) self.gateway_node.broadcast.reset_mock() self.assertEqual(1, len(self.gateway_node.in_progress_blocks)) key_message = KeyMessage(Sha256Hash(block_hash), self.TEST_NETWORK_NUM, "", key) self.sut.msg_key(key_message) self._assert_block_sent(ont_block)
def test_get_txs_block_recovery_encrypted(self): block: BlockOntMessage = self.ont_block() transactions: List[TxOntMessage] = self.ont_transactions(block) # assign short ids that the local connection won't know about until it gets the txs message remote_transaction_service = ExtensionTransactionService( MockNode(gateway_helpers.get_gateway_opts(8999)), 0) short_id_mapping = {} for i, transaction in enumerate(transactions): tx_hash = transaction.tx_hash() remote_transaction_service.assign_short_id(tx_hash, i + 1) remote_transaction_service.set_transaction_contents( tx_hash, transaction.rawbytes()) short_id_mapping[tx_hash] = TransactionInfo( tx_hash, transaction.rawbytes(), i + 1) bx_block = bytes( self.gateway_node.message_converter.block_to_bx_block( block, remote_transaction_service)[0]) self.gateway_node.block_recovery_service.add_block = \ MagicMock(wraps=self.gateway_node.block_recovery_service.add_block) self.gateway_node.send_msg_to_node = MagicMock() self.gateway_node.broadcast = MagicMock() key, ciphertext = symmetric_encrypt(bx_block) block_hash = crypto.double_sha256(ciphertext) key_message = KeyMessage(Sha256Hash(block_hash), DEFAULT_NETWORK_NUM, "", key) broadcast_message = BroadcastMessage(Sha256Hash(block_hash), DEFAULT_NETWORK_NUM, "", BroadcastMessageType.BLOCK, True, ciphertext) self.sut.msg_broadcast(broadcast_message) self.gateway_node.broadcast.reset_mock() self.sut.msg_key(key_message) self.gateway_node.block_recovery_service.add_block.assert_called_once() self.assertEqual(2, self.gateway_node.broadcast.call_count) recovery_broadcast = self.gateway_node.broadcast.call_args_list[0] ((gettxs_message, ), recovery_kwargs) = recovery_broadcast self.assertIsInstance(gettxs_message, GetTxsMessage) self.assertIn(ConnectionType.RELAY_TRANSACTION, recovery_kwargs["connection_types"]) key_broadcast = self.gateway_node.broadcast.call_args_list[1] ((key_message, _conn), recovery_kwargs) = key_broadcast self.assertIsInstance(key_message, KeyMessage) self.assertIn(ConnectionType.GATEWAY, recovery_kwargs["connection_types"]) txs = [tx for tx in short_id_mapping.values()] txs_message = TxsMessage(txs=txs) self.sut.msg_txs(txs_message) self._assert_block_sent(block)
def encrypt_and_add_payload(self, payload): """ Encrypts payload, computing a hash and storing it along with the key for later release. If encryption is disabled for dev, store ciphertext identical to hash_key. """ key, ciphertext = symmetric_encrypt(bytes(payload)) hash_key = crypto.double_sha256(ciphertext) self._add(hash_key, key, ciphertext, payload) return ciphertext, hash_key
def broadcast_key_pair(short_ids=None, network_num=0): if short_ids is None: short_ids = [1, 10, 99, 187] broadcast_message_hash = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN)) broadcast_message_bytes = bytearray(constants.UL_ULL_SIZE_IN_BYTES) broadcast_message_bytes.extend(helpers.generate_bytearray(500)) struct.pack_into("<Q", broadcast_message_bytes, 0, len(broadcast_message_bytes)) broadcast_message_bytes.extend(compact_block_short_ids_serializer.serialize_short_ids_into_bytes(short_ids)) key_bytes, enc_broadcast_message_bytes = crypto.symmetric_encrypt(bytes(broadcast_message_bytes)) broadcast_message = BroadcastMessage(broadcast_message_hash, network_num, "", True, enc_broadcast_message_bytes) key_message = KeyMessage(broadcast_message_hash, network_num, "", key_bytes) return broadcast_message, key_message