Beispiel #1
0
    def test_waiting_confirmation_timeout(self):
        block_hash_1 = Sha256Hash(helpers.generate_hash())
        block_msg_1 = create_block_message(block_hash_1)

        block_hash_2 = Sha256Hash(helpers.generate_hash())
        block_msg_2 = create_block_message(block_hash_2, block_hash_1)

        # first block gets sent immediately
        self.block_queuing_service.push(block_hash_1, block_msg_1)
        self.block_queuing_service.push(block_hash_2, block_msg_2)

        self.assertEqual(1, len(self.node.broadcast_to_nodes_messages))
        self.assertEqual(block_msg_1, self.node.broadcast_to_nodes_messages[0])
        self.assertEqual(1, len(self.block_queuing_service))
        self.assertIn(block_hash_1, self.block_queuing_service)
        self.assertIn(block_hash_2, self.block_queuing_service)

        time.time = MagicMock(return_value=time.time() +
                              gateway_constants.MAX_INTERVAL_BETWEEN_BLOCKS_S)
        self.node.alarm_queue.fire_alarms()

        self.assertEqual(2, len(self.node.broadcast_to_nodes_messages))
        self.assertEqual(block_msg_2, self.node.broadcast_to_nodes_messages[1])
        self.assertEqual(0, len(self.block_queuing_service))
        self.assertIn(block_hash_1, self.block_queuing_service)
        self.assertIn(block_hash_2, self.block_queuing_service)
Beispiel #2
0
    def test_waiting_confirmation_timeout(self):
        block_hash_1 = Sha256Hash(helpers.generate_hash())
        block_msg_1 = helpers.create_block_message(block_hash_1)

        block_hash_2 = Sha256Hash(helpers.generate_hash())
        block_msg_2 = helpers.create_block_message(block_hash_2, block_hash_1)

        # first block gets sent immediately
        self.node.block_queuing_service_manager.push(block_hash_1, block_msg_1)
        self.node.block_queuing_service_manager.push(block_hash_2, block_msg_2)

        self._assert_length_of_enqueued_messages(1)
        self._assert_block_in_enqueued_messages_index(block_msg_1, 0)
        self._assert_len_of_block_queuing_services(1)
        self._assert_block_in_queuing_services(block_hash_1)
        self._assert_block_in_queuing_services(block_hash_2)

        time.time = MagicMock(
            return_value=time.time()
            + gateway_constants.MAX_INTERVAL_BETWEEN_BLOCKS_S
        )
        self.node.alarm_queue.fire_alarms()

        self._assert_length_of_enqueued_messages(2)
        self._assert_block_in_enqueued_messages_index(block_msg_2, 1)
        self._assert_len_of_block_queuing_services(0)
        self._assert_block_in_queuing_services(block_hash_1)
        self._assert_block_in_queuing_services(block_hash_2)
Beispiel #3
0
    def test_block_added_waiting_for_previous_block_confirmation(self):
        block_hash_1 = Sha256Hash(helpers.generate_hash())
        block_msg_1 = create_block_message(block_hash_1)

        block_hash_2 = Sha256Hash(helpers.generate_hash())
        block_msg_2 = create_block_message(block_hash_2, block_hash_1)

        # first block gets sent immediately
        self.block_queuing_service.push(block_hash_1, block_msg_1)
        self.assertEqual(1, len(self.node.broadcast_to_nodes_messages))
        self.assertEqual(block_msg_1, self.node.broadcast_to_nodes_messages[0])
        self.assertEqual(0, len(self.block_queuing_service))
        self.assertIn(block_hash_1, self.block_queuing_service)

        # no confirmation, wait on block 1
        self.block_queuing_service.push(block_hash_2, block_msg_2)
        self.assertEqual(1, len(self.node.broadcast_to_nodes_messages))
        self.assertEqual(block_msg_1, self.node.broadcast_to_nodes_messages[0])
        self.assertEqual(1, len(self.block_queuing_service))
        self.assertIn(block_hash_1, self.block_queuing_service)
        self.assertIn(block_hash_2, self.block_queuing_service)

        self.block_queuing_service.mark_blocks_seen_by_blockchain_node(
            [block_hash_1])
        self.assertEqual(2, len(self.node.broadcast_to_nodes_messages))
        self.assertEqual(block_msg_2, self.node.broadcast_to_nodes_messages[1])
        self.assertEqual(0, len(self.block_queuing_service))
Beispiel #4
0
    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)
Beispiel #5
0
    def test_broadcast_to_connection_type(self):
        relay_all_conn = self._add_connection(0, 9000, ALL_NETWORK_NUM, ConnectionType.RELAY_ALL)
        relay_block_conn = self._add_connection(1, 9001, ALL_NETWORK_NUM, ConnectionType.RELAY_BLOCK)
        relay_transaction_conn = self._add_connection(2, 9002, ALL_NETWORK_NUM, ConnectionType.RELAY_TRANSACTION)
        gateway_conn = self._add_connection(3, 9003, ALL_NETWORK_NUM, ConnectionType.EXTERNAL_GATEWAY)

        block_message = BroadcastMessage(Sha256Hash(helpers.generate_hash()), ALL_NETWORK_NUM, "",
                                         BroadcastMessageType.BLOCK, False, helpers.generate_bytearray(250))
        self.sut.broadcast(block_message, BroadcastOptions(connection_types=[ConnectionType.RELAY_BLOCK]))

        tx_message = BroadcastMessage(Sha256Hash(helpers.generate_hash()), ALL_NETWORK_NUM, "",
                                      BroadcastMessageType.BLOCK, False, helpers.generate_bytearray(250))
        self.sut.broadcast(tx_message, BroadcastOptions(connection_types=[ConnectionType.RELAY_TRANSACTION]))

        gateway_message = BroadcastMessage(Sha256Hash(helpers.generate_hash()), ALL_NETWORK_NUM, "",
                                           BroadcastMessageType.BLOCK, False, helpers.generate_bytearray(250))
        self.sut.broadcast(gateway_message, BroadcastOptions(connection_types=[ConnectionType.GATEWAY]))

        self.assertIn(block_message, relay_all_conn.enqueued_messages)
        self.assertIn(block_message, relay_block_conn.enqueued_messages)
        self.assertNotIn(block_message, relay_transaction_conn.enqueued_messages)
        self.assertNotIn(block_message, gateway_conn.enqueued_messages)

        self.assertIn(tx_message, relay_all_conn.enqueued_messages)
        self.assertNotIn(tx_message, relay_block_conn.enqueued_messages)
        self.assertIn(tx_message, relay_transaction_conn.enqueued_messages)
        self.assertNotIn(tx_message, gateway_conn.enqueued_messages)

        self.assertNotIn(gateway_message, relay_all_conn.enqueued_messages)
        self.assertNotIn(gateway_message, relay_block_conn.enqueued_messages)
        self.assertNotIn(gateway_message, relay_transaction_conn.enqueued_messages)
        self.assertIn(gateway_message, gateway_conn.enqueued_messages)
    def test_waiting_recovery_last_block_is_removed(self):
        block_hash1 = Sha256Hash(helpers.generate_hash())
        block_msg1 = helpers.create_block_message(block_hash1)

        block_hash2 = Sha256Hash(helpers.generate_hash())
        block_msg2 = helpers.create_block_message(block_hash2, block_hash1)

        block_hash3 = Sha256Hash(helpers.generate_hash())
        block_msg3 = helpers.create_block_message(block_hash3, block_hash2)

        self.node.block_queuing_service_manager.push(
            block_hash1, block_msg1, waiting_for_recovery=False)
        self.node.block_queuing_service_manager.push(
            block_hash2, block_msg2, waiting_for_recovery=False)
        self.node.block_queuing_service_manager.push(block_hash3,
                                                     block_msg3,
                                                     waiting_for_recovery=True)

        self._assert_length_of_enqueued_messages(1)
        self._assert_len_of_block_queuing_services(2)
        self._assert_block_in_enqueued_messages_index(block_msg1, 0)

        self._reset_enqueue_msg_mocks()

        self.block_queuing_service.remove(block_hash3)
        self.block_queuing_service_2.remove(block_hash3)

        self._assert_length_of_enqueued_messages(0)
        self._assert_len_of_block_queuing_services(1)

        self._mark_blocks_seen_by_blockchain_nodes([block_hash1])
        self._assert_length_of_enqueued_messages(1)
        self._assert_len_of_block_queuing_services(0)
        self._assert_block_in_enqueued_messages_index(block_msg2, 0)
Beispiel #7
0
    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_object_size(self):
        mock_node = MockNode(get_common_opts(1234))
        object_size = memory_utils.get_object_size(mock_node)

        self.assertIsInstance(object_size, ObjectSize)
        self.assertTrue(object_size.size > 0)
        self.assertTrue(object_size.flat_size > 0)
        self.assertTrue(object_size.is_actual_size)
        self.assertEqual(0, len(object_size.references))

        ex_set = ExpiringSet(AlarmQueue(), 10, "testset")
        s = set()
        h1 = Sha256Hash(b"1" * 32)
        h2 = Sha256Hash(b"0" * 32)
        print(memory_utils.get_object_size(ex_set).size)
        print(memory_utils.get_object_size(s).size)
        print(memory_utils.get_object_size(h1).size)
        print(memory_utils.get_object_size(h2).size)
        print(memory_utils.get_special_size(ex_set).size)
        print(memory_utils.get_special_size(s).size)
        print(memory_utils.get_special_size(h1).size)
        print(memory_utils.get_special_size(h2).size)
        ex_set.add(h1)
        ex_set.add(h2)
        s.add(h1)
        s.add(h2)
        print(memory_utils.get_object_size(ex_set).size)
        print(memory_utils.get_special_size(ex_set).size)
        print(memory_utils.get_object_size(s).size)
Beispiel #9
0
    def test_berlin_block_from_bytes(self):
        block: Block = rlp.decode(eth_fixtures.BERLIN_BLOCK, Block)

        self.assertEqual(
            Sha256Hash.from_string(
                "0ad3836807aa90218884be62c8dd912fe5228aafa6fc2a7c21028e8c09bc91ef"
            ),
            block.header.hash_object(),
        )
        self.assertEqual(2, len(block.transactions))

        legacy_tx = block.transactions[0]
        self.assertIsInstance(legacy_tx, LegacyTransaction)
        self.assertEqual(
            Sha256Hash.from_string(
                "77b19baa4de67e45a7b26e4a220bccdbb6731885aa9927064e239ca232023215"
            ),
            legacy_tx.hash(),
        )

        acl_tx = block.transactions[1]
        self.assertIsInstance(acl_tx, AccessListTransaction)
        self.assertEqual(
            Sha256Hash.from_string(
                "554af720acf477830f996f1bc5d11e54c38aa40042aeac6f66cb66f9084a959d"
            ),
            acl_tx.hash(),
        )

        re_encoded = rlp.encode(block)
        self.assertEqual(block, rlp.decode(re_encoded, Block))
 def _test_mark_blocks_and_request_cleanup(self):
     marked_block = Sha256Hash(
         binary=helpers.generate_bytearray(SHA256_HASH_LEN))
     prev_block = Sha256Hash(
         binary=helpers.generate_bytearray(SHA256_HASH_LEN))
     tracked_blocks = []
     self.cleanup_service.on_new_block_received(marked_block, prev_block)
     self.transaction_service.track_seen_short_ids(marked_block, [])
     for _ in range(self.block_confirmations_count - 1):
         tracked_block = Sha256Hash(
             binary=helpers.generate_bytearray(SHA256_HASH_LEN))
         self.transaction_service.track_seen_short_ids(tracked_block, [])
         tracked_blocks.append(tracked_block)
     unmarked_block = Sha256Hash(
         binary=helpers.generate_bytearray(SHA256_HASH_LEN))
     self.assertIsNone(self.cleanup_service.last_confirmed_block)
     self.cleanup_service.mark_blocks_and_request_cleanup(
         [marked_block, *tracked_blocks])
     self.assertEqual(marked_block,
                      self.cleanup_service.last_confirmed_block)
     self.assertTrue(
         self.cleanup_service.is_marked_for_cleanup(marked_block))
     self.assertFalse(
         self.cleanup_service.is_marked_for_cleanup(unmarked_block))
     self.assertEqual(marked_block,
                      self.cleanup_service.last_confirmed_block)
Beispiel #11
0
    def test_txs_with_short_ids_message(self):
        txs_info = [
            TransactionInfo(Sha256Hash(helpers.generate_bytearray(32)),
                            helpers.generate_bytearray(200), 111),
            TransactionInfo(Sha256Hash(helpers.generate_bytearray(32)),
                            helpers.generate_bytearray(300), 222),
            TransactionInfo(Sha256Hash(helpers.generate_bytearray(32)),
                            helpers.generate_bytearray(400), 333)
        ]

        msg = TxsMessage(txs=txs_info)

        msg_bytes = msg.rawbytes()

        self.assertTrue(msg_bytes)

        parsed_msg = TxsMessage(buf=msg_bytes)

        self.assertTrue(parsed_msg)

        parsed_txs_info = parsed_msg.get_txs()

        self.assertEqual(len(parsed_txs_info), len(txs_info))

        for index in range(len(txs_info)):
            self.assertEqual(parsed_txs_info[index].short_id,
                             txs_info[index].short_id)
            self.assertEqual(parsed_txs_info[index].contents,
                             txs_info[index].contents)
            self.assertEqual(parsed_txs_info[index].hash, txs_info[index].hash)
    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)
Beispiel #13
0
    def test_block_added_waiting_for_previous_block_confirmation(self):
        block_hash_1 = Sha256Hash(helpers.generate_hash())
        block_msg_1 = helpers.create_block_message(block_hash_1)

        block_hash_2 = Sha256Hash(helpers.generate_hash())
        block_msg_2 = helpers.create_block_message(block_hash_2, block_hash_1)

        # first block gets sent immediately
        self.node.block_queuing_service_manager.push(block_hash_1, block_msg_1)
        self._assert_length_of_enqueued_messages(1)
        self._assert_block_in_enqueued_messages_index(block_msg_1, 0)
        self._assert_len_of_block_queuing_services(0)
        self._assert_block_in_queuing_services(block_hash_1)

        # no confirmation, wait on block 1
        self.node.block_queuing_service_manager.push(block_hash_2, block_msg_2)
        self._assert_length_of_enqueued_messages(1)
        self._assert_block_in_enqueued_messages_index(block_msg_1, 0)
        self._assert_len_of_block_queuing_services(1)
        self._assert_block_in_queuing_services(block_hash_1)
        self._assert_block_in_queuing_services(block_hash_2)

        self._mark_blocks_seen_by_blockchain_nodes(
            [block_hash_1]
        )
        self._assert_length_of_enqueued_messages(2)
        self._assert_block_in_enqueued_messages_index(block_msg_2, 1)
        self._assert_len_of_block_queuing_services(0)
Beispiel #14
0
    def test_block_removed_with_ttl_check(self):
        self.node.has_active_blockchain_peer = MagicMock(return_value=False)

        block_hash_start = Sha256Hash(helpers.generate_hash())
        block_msg_start = helpers.create_block_message(block_hash_start)
        block_hash_end = Sha256Hash(helpers.generate_hash())
        block_msg_end = helpers.create_block_message(block_hash_end)
        self.node.block_queuing_service_manager.push(block_hash_start, block_msg_start)

        for i in range(2, BLOCK_QUEUE_LENGTH_LIMIT + 1):
            block_hash = Sha256Hash(helpers.generate_hash())
            block_msg = helpers.create_block_message(block_hash)
            self.node.block_queuing_service_manager.push(block_hash, block_msg)

        self.assertEqual(BLOCK_QUEUE_LENGTH_LIMIT, len(self.block_queuing_service))
        self._assert_length_of_enqueued_messages(0)

        self.node.has_active_blockchain_peer = MagicMock(return_value=True)
        time.time = MagicMock(
            return_value=time.time()
            + MAX_BLOCK_CACHE_TIME_S * 2
        )
        self.assertEqual(BLOCK_QUEUE_LENGTH_LIMIT, len(self.block_queuing_service._block_queue))
        self.node.block_queuing_service_manager.push(block_hash_end, block_msg_end)
        self._mark_blocks_seen_by_blockchain_nodes([block_hash_end])
        self.assertEqual(0, len(self.block_queuing_service._block_queue))
    def _tx_cache_key_to_hash(self, transaction_cache_key) -> Sha256Hash:
        if isinstance(transaction_cache_key, Sha256Hash):
            return transaction_cache_key

        if isinstance(transaction_cache_key, (bytes, bytearray, memoryview)):
            return Sha256Hash(transaction_cache_key)

        return Sha256Hash(bytearray(transaction_cache_key.binary()))
Beispiel #16
0
def create_block_message(
    block_hash: Optional[Sha256Hash] = None,
    previous_block_hash: Optional[Sha256Hash] = None,
) -> AbstractBlockMessage:
    if block_hash is None:
        block_hash = Sha256Hash(generate_hash())
    if previous_block_hash is None:
        previous_block_hash = Sha256Hash(generate_hash())
    return TestBlockMessage(previous_block_hash, block_hash)
Beispiel #17
0
    def _tx_cache_key_to_hash(self, transaction_cache_key: Union[Sha256Hash, bytes, bytearray, memoryview, str]) \
            -> Sha256Hash:
        if isinstance(transaction_cache_key, Sha256Hash):
            return transaction_cache_key

        if isinstance(transaction_cache_key, (bytes, bytearray, memoryview)):
            return Sha256Hash(transaction_cache_key)

        return Sha256Hash(convert.hex_to_bytes(transaction_cache_key))
    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)
Beispiel #19
0
    def _wrap_sha256(
        self, transaction_hash: Union[bytes, bytearray, memoryview, Sha256Hash]
    ) -> Sha256Hash:
        if isinstance(transaction_hash, Sha256Hash):
            return transaction_hash

        if isinstance(transaction_hash, (bytes, bytearray, memoryview)):
            return Sha256Hash(binary=transaction_hash)

        return Sha256Hash(binary=convert.hex_to_bytes(transaction_hash))
Beispiel #20
0
    def test_init(self):
        with self.assertRaises(ValueError):
            Sha256Hash(bytearray([i for i in range(SHA256_HASH_LEN - 1)]))
        with self.assertRaises(ValueError):
            Sha256Hash(bytearray())

        expected = self.int_hash_31a.binary
        actual = self.to_31
        self.assertEqual(expected, actual)
        actual = Sha256Hash(memoryview(actual))
        self.assertEqual(expected, actual.binary)
        self.assertIsNotNone(hash(self.int_hash_all_0))
    def test_place_hold(self):
        hash1 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN))
        hash2 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN))

        self.sut.place_hold(hash1, self.dummy_connection)
        self.sut.place_hold(hash2, self.dummy_connection)

        self.assertEqual(2, len(self.sut._holds.contents))
        self.assertEqual(2, len(self.node.broadcast_messages))
        self.assertEqual(BlockHoldingMessage(hash1, network_num=1),
                         self.node.broadcast_messages[0][0])
        self.assertEqual(BlockHoldingMessage(hash2, network_num=1),
                         self.node.broadcast_messages[1][0])
    def _test_track_short_ids_seen_in_block(self):
        short_ids = [1, 2, 3, 4, 5]
        transaction_hashes = list(map(crypto.double_sha256, map(bytes, short_ids)))
        transaction_contents = list(map(crypto.double_sha256, transaction_hashes))

        for i, short_id in enumerate(short_ids):
            transaction_key = self.transaction_service.get_transaction_key(transaction_hashes[i])
            self.transaction_service._tx_cache_key_to_contents[transaction_key.transaction_cache_key] = \
                transaction_contents[i]
            self.transaction_service.assign_short_id_by_key(transaction_key, short_id)

        self.transaction_service.set_final_tx_confirmations_count(7)
        # 1st block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [1])
        self._verify_txs_in_tx_service([1, 2, 3, 4, 5], [])

        # 2nd block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [2])
        self._verify_txs_in_tx_service([1, 2, 3, 4, 5], [])

        # 3rd block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [3, 4])
        self._verify_txs_in_tx_service([1, 2, 3, 4, 5], [])

        # 4th block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [])
        self._verify_txs_in_tx_service([1, 2, 3, 4, 5], [])

        # 5th block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [])
        self._verify_txs_in_tx_service([1, 2, 3, 4, 5], [])

        # 6th block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [])
        self._verify_txs_in_tx_service([1, 2, 3, 4, 5], [])

        # 7th block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [])
        self._verify_txs_in_tx_service([2, 3, 4], [0, 1])

        # 8th block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [])
        self._verify_txs_in_tx_service([3, 4], [0, 1, 2])

        # 9th block with short ids arrives
        block_hash = bytearray(helpers.generate_bytearray(32))
        self.transaction_service.track_seen_short_ids(Sha256Hash(block_hash), [])
        self._verify_txs_in_tx_service([], [0, 1, 2, 3, 4])
    def test_place_hold_duplicates(self):
        hash1 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN))
        hash2 = Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN))

        self.sut.place_hold(hash1, self.dummy_connection)
        time.time = MagicMock(return_value=time.time() + 5)

        self.sut.place_hold(hash1, self.dummy_connection)
        self.sut.place_hold(hash1, self.dummy_connection)
        self.sut.place_hold(hash2, self.dummy_connection)

        self.assertEqual(2, len(self.sut._holds.contents))
        hold1 = self.sut._holds.contents[hash1]
        hold2 = self.sut._holds.contents[hash2]
        self.assertTrue(hold2.hold_message_time - hold1.hold_message_time >= 5)
Beispiel #24
0
    def test_last_block_is_recovered(self):
        block_hash1 = Sha256Hash(helpers.generate_hash())
        block_msg1 = helpers.create_block_message()

        block_hash2 = Sha256Hash(helpers.generate_hash())
        block_msg2 = helpers.create_block_message(block_hash2, block_hash1)

        block_hash3 = Sha256Hash(helpers.generate_hash())
        block_msg3 = helpers.create_block_message(block_hash3, block_hash2)

        self.node.block_queuing_service_manager.push(
            block_hash1, block_msg1, waiting_for_recovery=False
        )
        self._mark_block_seen_by_blockchain_nodes(
            block_hash1, None
        )
        self.node.block_queuing_service_manager.push(
            block_hash2, block_msg2, waiting_for_recovery=False
        )
        self._mark_block_seen_by_blockchain_nodes(
            block_hash2, None
        )
        self.node.block_queuing_service_manager.push(
            block_hash3, block_msg3, waiting_for_recovery=True
        )

        self._assert_length_of_enqueued_messages(2)
        self._assert_len_of_block_queuing_services(1)
        self._assert_block_in_enqueued_messages_index(block_msg1, 0)
        self._assert_block_in_enqueued_messages_index(block_msg2, 1)

        self._reset_enqueue_msg_mocks()
        self._reset_enqueue_msg_mocks()

        # don't send, since not recovered enough though timeout
        time.time = MagicMock(
            return_value=time.time() + MAX_INTERVAL_BETWEEN_BLOCKS_S
        )
        self.node.alarm_queue.fire_alarms()
        self._assert_length_of_enqueued_messages(0)
        self._assert_len_of_block_queuing_services(1)

        self.node.block_queuing_service_manager.update_recovered_block(
            block_hash3, block_msg3
        )
        self._assert_length_of_enqueued_messages(1)
        self._assert_len_of_block_queuing_services(0)
        self._assert_block_in_enqueued_messages_index(block_msg3, 0)
Beispiel #25
0
    def _parse(self):
        txs = []

        off = constants.BX_HDR_COMMON_OFF

        txs_count, = struct.unpack_from('<L', self.buf, off)
        off += constants.UL_INT_SIZE_IN_BYTES

        logger.debug("Block recovery: received {0} txs in the message.".format(txs_count))

        for tx_index in range(txs_count):
            tx_sid, = struct.unpack_from('<L', self.buf, off)
            off += constants.UL_INT_SIZE_IN_BYTES

            tx_hash = Sha256Hash(self._memoryview[off:off + bxcommon.utils.crypto.SHA256_HASH_LEN])
            off += bxcommon.utils.crypto.SHA256_HASH_LEN

            tx_size, = struct.unpack_from('<L', self.buf, off)
            off += constants.UL_INT_SIZE_IN_BYTES

            tx = self._memoryview[off:off + tx_size]
            off += tx_size

            txs.append(TransactionInfo(tx_hash, tx, tx_sid))

        self._txs = txs
    def test_update_recovered_block(self):
        block_queuing_service = self.node.build_block_queuing_service(
            self.node_conn)
        self.node.block_queuing_service_manager.add_block_queuing_service(
            self.node_conn, block_queuing_service)
        block_queuing_service.update_recovered_block = MagicMock()
        block_queuing_service_2 = self.node.build_block_queuing_service(
            self.node_conn_2)
        self.node.block_queuing_service_manager.add_block_queuing_service(
            self.node_conn_2, block_queuing_service_2)
        block_queuing_service_2.update_recovered_block = MagicMock()
        block_queuing_service_3 = self.node.build_block_queuing_service(
            self.node_conn_3)
        self.node.block_queuing_service_manager.add_block_queuing_service(
            self.node_conn_3, block_queuing_service_3)
        block_queuing_service_3.update_recovered_block = MagicMock()
        self.assertEqual(
            len(self.node.block_queuing_service_manager.
                blockchain_peer_to_block_queuing_service), 3)

        block_hash = Sha256Hash(helpers.generate_hash())
        block_msg = helpers.create_block_message(block_hash)
        self.node.block_queuing_service_manager.update_recovered_block(
            block_hash, block_msg)
        block_queuing_service.update_recovered_block.assert_called_with(
            block_hash, block_msg)
        block_queuing_service_2.update_recovered_block.assert_called_with(
            block_hash, block_msg)
        block_queuing_service_3.update_recovered_block.assert_called_with(
            block_hash, block_msg)

        self.assertIn(block_hash, self.node.block_storage)
        self.assertEqual(block_msg, self.node.block_storage[block_hash])
    def test_remove_block(self):
        block_queuing_service = self.node.build_block_queuing_service(
            self.node_conn)
        self.node.block_queuing_service_manager.add_block_queuing_service(
            self.node_conn, block_queuing_service)
        block_queuing_service.remove = MagicMock()
        block_queuing_service_2 = self.node.build_block_queuing_service(
            self.node_conn_2)
        self.node.block_queuing_service_manager.add_block_queuing_service(
            self.node_conn_2, block_queuing_service_2)
        block_queuing_service_2.remove = MagicMock()

        block_hash = Sha256Hash(helpers.generate_hash())
        block_msg = helpers.create_block_message(block_hash)

        self.node.block_queuing_service_manager.store_block_data(
            block_hash, block_msg)
        block_queuing_service._blocks.add(block_hash)
        block_queuing_service_2._blocks.add(block_hash)
        self.assertIn(block_hash, self.node.block_storage)
        self.assertEqual(block_msg, self.node.block_storage[block_hash])

        self.node.block_queuing_service_manager.remove(block_hash)
        self.assertNotIn(block_hash, self.node.block_storage)
        block_queuing_service.remove.assert_called_with(block_hash)
        block_queuing_service_2.remove.assert_called_with(block_hash)
    def add_block(self, bx_block: memoryview, block_hash: Sha256Hash,
                  unknown_tx_sids: List[int],
                  unknown_tx_hashes: List[Sha256Hash]):
        """
        Adds a block that needs to recovery. Tracks unknown short ids and contents as they come in.
        :param bx_block: bytearray representation of compressed block
        :param block_hash: original ObjectHash of block
        :param unknown_tx_sids: list of unknown short ids
        :param unknown_tx_hashes: list of unknown tx ObjectHashes
        """
        logger.trace(
            "Recovering block with {} unknown short ids and {} contents: {}",
            len(unknown_tx_sids), len(unknown_tx_hashes), block_hash)
        bx_block_hash = Sha256Hash(crypto.double_sha256(bx_block))

        self._bx_block_hash_to_block[bx_block_hash] = bx_block
        self._bx_block_hash_to_block_hash[bx_block_hash] = block_hash
        self._bx_block_hash_to_sids[bx_block_hash] = set(unknown_tx_sids)
        self._bx_block_hash_to_tx_hashes[bx_block_hash] = set(
            unknown_tx_hashes)

        self._block_hash_to_bx_block_hashes[block_hash].add(bx_block_hash)
        for sid in unknown_tx_sids:
            self._sid_to_bx_block_hashes[sid].add(bx_block_hash)
        for tx_hash in unknown_tx_hashes:
            self._tx_hash_to_bx_block_hashes[tx_hash].add(bx_block_hash)

        self._blocks_expiration_queue.add(bx_block_hash)
        self._schedule_cleanup()
Beispiel #29
0
    async def test_blxr_tx_from_json(self):
        tx_json = {
            'from': '0xc165599b5e418bb9d8a19090696ea2403b2927ed',
            'gas': "0x5208",
            'gasPrice': "0xc1b759d70",
            'hash': '0xd569674ad9fcaaedcb6867b7896067b445d4a838316be4292c474df17bf4bd50',
            'input': '0x',
            'nonce': "0x14",
            'to': '0xdb5f0c1f4198bc6ffa98b35f7188f82740b8caf7',
            'value': "0x3e871b540c000",
            'v': '0x26',
            'r': '0x484bc950fb2d595500baa604774cb8d156a677198e087801936f38ca0b27049',
            's': '0x7ca82ef7b6938c2e96966dd940b186c9cdc0c7f42b2843adbc0751bb6e67a2d4'
        }

        result = await self.request(BxJsonRpcRequest(
            "1",
            RpcRequestType.BLXR_TX,
            {
                rpc_constants.TRANSACTION_JSON_PARAMS_KEY: tx_json,
                "quota_type": "paid_daily_quota"
            }
        ))
        self.assertEqual("1", result.id)
        self.assertIsNone(result.error)
        self.assertEqual("ad6f9332384194f80d8e49af8f093ad019b3f6b7173eb2956a46c9a0d8c4d03c", result.result["tx_hash"])
        self.assertEqual(ACCOUNT_ID, result.result["account_id"])
        self.assertEqual("paid_daily_quota", result.result["quota_type"])

        self.assertEqual(1, len(self.gateway_node.broadcast_messages))
        self.assertEqual(
            Sha256Hash(convert.hex_to_bytes("ad6f9332384194f80d8e49af8f093ad019b3f6b7173eb2956a46c9a0d8c4d03c")),
            self.gateway_node.broadcast_messages[0][0].tx_hash()
        )
Beispiel #30
0
    def test_propagate_block_to_network_unencrypted_block(self):
        self.node.opts.encrypt_blocks = False

        block_message = helpers.generate_bytearray(50)
        block_info = BlockInfo(
            Sha256Hash(helpers.generate_bytearray(crypto.SHA256_HASH_LEN)), [],
            datetime.datetime.utcnow(), datetime.datetime.utcnow(), 0, 1,
            helpers.generate_bytearray(crypto.SHA256_HASH_LEN),
            helpers.generate_bytearray(crypto.SHA256_HASH_LEN), 0, 0, 0, [])

        connection = MockConnection(
            MockSocketConnection(1, self.node, ip_address=LOCALHOST,
                                 port=9000), self.node)
        self.neutrality_service.propagate_block_to_network(
            block_message, connection, block_info)

        self.assertEqual(1, len(self.node.broadcast_messages))
        broadcast_message, connection_types = self.node.broadcast_messages[0]
        # self.assertTrue(any(ConnectionType.RELAY_BLOCK & connection_type for connection_type in connection_types))
        self.assertTrue(
            all(ConnectionType.RELAY_BLOCK in connection_type
                for connection_type in connection_types))
        self.assertEqual(block_info.block_hash, broadcast_message.block_hash())

        self.assertNotIn(block_info.block_hash,
                         self.node.in_progress_blocks._cache)
        self.assertNotIn(broadcast_message.block_hash(),
                         self.neutrality_service._receipt_tracker)