Esempio n. 1
0
    def msg_new_block_hashes(self, msg: NewBlockHashesEthProtocolMessage):
        if not self.node.should_process_block_hash(msg.block_hash()):
            return

        block_hash_number_pairs = []
        for block_hash, block_number in msg.get_block_hash_number_pairs():
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.BLOCK_ANNOUNCED_BY_BLOCKCHAIN_NODE,
                network_num=self.connection.network_num,
                more_info="Protocol: {}, Network: {}. {}".format(
                    self.node.opts.blockchain_protocol,
                    self.node.opts.blockchain_network, msg.extra_stats_data()),
                block_height=block_number,
            )
            gateway_bdn_performance_stats_service.log_block_message_from_blockchain_node(
                False)

            if block_hash in self.node.blocks_seen.contents:
                self.node.on_block_seen_by_blockchain_node(
                    block_hash, block_number=block_number)
                block_stats.add_block_event_by_block_hash(
                    block_hash,
                    BlockStatEventType.
                    BLOCK_RECEIVED_FROM_BLOCKCHAIN_NODE_IGNORE_SEEN,
                    network_num=self.connection.network_num,
                    block_height=block_number,
                )
                self.connection.log_info(
                    "Ignoring duplicate block {} from local blockchain node.",
                    block_hash)
                continue

            recovery_cancelled = self.node.on_block_seen_by_blockchain_node(
                block_hash, block_number=block_number)
            if recovery_cancelled:
                continue

            self.node.track_block_from_node_handling_started(block_hash)
            block_hash_number_pairs.append((block_hash, block_number))

            self.connection.log_info(
                "Fetching block {} from local Ethereum node.", block_hash)

        if not block_hash_number_pairs:
            return

        for block_hash, block_number in block_hash_number_pairs:
            # pyre-fixme[6]: Expected `memoryview` for 1st param but got `None`.
            self.pending_new_block_parts.add(
                block_hash, NewBlockParts(None, None, block_number))
            self.connection.enqueue_msg(
                GetBlockHeadersEthProtocolMessage(None, block_hash.binary, 1,
                                                  0, False))

        self.request_block_body(
            [block_hash for block_hash, _ in block_hash_number_pairs])
Esempio n. 2
0
    def test_complete_header_body_recovery(self):
        self.node.block_processing_service.queue_block_for_processing = MagicMock()
        self.node.block_queuing_service_manager.push = MagicMock()
        self.node.on_block_seen_by_blockchain_node = MagicMock(return_value=False)
        self.sut.is_valid_block_timestamp = MagicMock(return_value=True)

        header = mock_eth_messages.get_dummy_block_header(1)
        block = mock_eth_messages.get_dummy_block(1, header)
        block_hash = header.hash_object()
        new_block_hashes_message = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair(
            block_hash, 1
        )
        header_message = BlockHeadersEthProtocolMessage(None, [header])
        bodies_message = BlockBodiesEthProtocolMessage(None, [TransientBlockBody(block.transactions, block.uncles)])

        self.sut.msg_new_block_hashes(new_block_hashes_message)
        self.node.on_block_seen_by_blockchain_node.assert_called_once()

        self.assertEqual(1, len(self.sut.pending_new_block_parts.contents))
        self.assertEqual(2, len(self.enqueued_messages))

        self.node.on_block_seen_by_blockchain_node.reset_mock()
        self.node.on_block_seen_by_blockchain_node = MagicMock(return_value=True)
        self.sut.msg_block_headers(header_message)
        self.sut.msg_block_bodies(bodies_message)

        self.assertEqual(1, len(gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats))
        for stats in gateway_bdn_performance_stats_service.interval_data.blockchain_node_to_bdn_stats.values():
            self.assertEqual(1, stats.new_blocks_received_from_blockchain_node)
            self.assertEqual(0, stats.new_blocks_received_from_bdn)

        self.node.on_block_seen_by_blockchain_node.assert_called_once()
        self.node.block_queuing_service_manager.push.assert_not_called()
        self.node.block_processing_service.queue_block_for_processing.assert_not_called()
Esempio n. 3
0
    def send_block_to_node(
        self,
        block_hash: Sha256Hash,
        block_msg: Optional[InternalEthBlockInfo] = None,
    ) -> None:
        assert block_msg is not None

        # block must always be greater than previous best
        block_number = block_msg.block_number()
        best_height, _best_hash, _ = self.best_sent_block
        assert block_number > best_height

        new_block_parts = self.node.block_parts_storage[block_hash]

        if block_msg.has_total_difficulty():
            new_block_msg = block_msg.to_new_block_msg()
            super(EthBlockQueuingService,
                  self).send_block_to_node(block_hash, new_block_msg)
            self.node.set_known_total_difficulty(
                new_block_msg.block_hash(),
                new_block_msg.get_chain_difficulty())
        else:
            calculated_total_difficulty = self.node.try_calculate_total_difficulty(
                block_hash, new_block_parts)

            if calculated_total_difficulty is None:
                # Total difficulty may be unknown after a long fork or
                # if gateways just started. Announcing new block hashes to
                # ETH node in that case. It
                # will request header and body separately.
                new_block_headers_msg = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair(
                    block_hash, new_block_parts.block_number)
                super(EthBlockQueuingService,
                      self).send_block_to_node(block_hash,
                                               new_block_headers_msg)
            else:
                new_block_msg = NewBlockEthProtocolMessage.from_new_block_parts(
                    new_block_parts, calculated_total_difficulty)
                super(EthBlockQueuingService,
                      self).send_block_to_node(block_hash, new_block_msg)

        self.node.log_blocks_network_content(self.node.network_num, block_msg)
        self.sent_block_at_height[block_number] = block_hash
        self.best_sent_block = SentEthBlockInfo(block_number, block_hash,
                                                time.time())
        self._schedule_confirmation_check(block_hash)

        if self.node.opts.filter_txs_factor > 0:
            self.node.on_transactions_in_block(
                block_msg.to_new_block_msg().txns())
Esempio n. 4
0
    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)
Esempio n. 5
0
    def test_complete_header_body_fetch(self):
        self.node.block_processing_service.queue_block_for_processing = MagicMock()
        self.sut.is_valid_block_timestamp = MagicMock(return_value=True)

        header = mock_eth_messages.get_dummy_block_header(1)
        block = mock_eth_messages.get_dummy_block(1, header)
        block_hash = header.hash_object()
        new_block_hashes_message = NewBlockHashesEthProtocolMessage.from_block_hash_number_pair(
            block_hash, 1
        )
        header_message = BlockHeadersEthProtocolMessage(None, [header])
        bodies_message = BlockBodiesEthProtocolMessage(None, [TransientBlockBody(block.transactions, block.uncles)])

        self.sut.msg_new_block_hashes(new_block_hashes_message)
        self.assertEqual(1, len(self.sut.pending_new_block_parts.contents))
        self.assertEqual(2, len(self.enqueued_messages))

        self.sut.msg_block_headers(header_message)
        self.sut.msg_block_bodies(bodies_message)

        self.node.block_processing_service.queue_block_for_processing.assert_called_once()