def advance_bytes_written_to_socket(self, bytes_sent):
        if self.message_tracker and self.message_tracker.is_sending_block_message():
            assert self.node.opts.track_detailed_sent_messages

            entry = self.message_tracker.messages[0]
            super(AbstractGatewayBlockchainConnection, self).advance_bytes_written_to_socket(bytes_sent)

            if not self.message_tracker.is_sending_block_message():
                block_message = typing.cast(AbstractBlockMessage, entry.message)
                block_message_queue_time = entry.queued_time
                block_message_length = entry.length
                block_hash = block_message.block_hash()
                handling_time, relay_desc = self.node.track_block_from_bdn_handling_ended(block_hash)
                block_stats.add_block_event_by_block_hash(block_hash,
                                                          BlockStatEventType.BLOCK_SENT_TO_BLOCKCHAIN_NODE,
                                                          network_num=self.network_num,
                                                          more_info="{} in {}; Handled in {}; R - {}; {}".format(
                                                              stats_format.byte_count(
                                                                  block_message_length
                                                              ),
                                                              stats_format.timespan(
                                                                  block_message_queue_time,
                                                                  time.time()
                                                              ),
                                                              stats_format.duration(handling_time),
                                                              relay_desc,
                                                              block_message.extra_stats_data()
                                                          ))
        else:
            super(AbstractGatewayBlockchainConnection, self).advance_bytes_written_to_socket(bytes_sent)
Exemple #2
0
    def _propagate_encrypted_block_to_network(self, bx_block, connection,
                                              block_info):

        if block_info is None or block_info.block_hash is None:
            block_hash = b"Unknown"
            requested_by_peer = True
        else:
            block_hash = block_info.block_hash
            requested_by_peer = False

        encrypt_start_datetime = datetime.datetime.utcnow()
        encrypt_start_timestamp = time.time()
        encrypted_block, raw_cipher_hash = self._node.in_progress_blocks.encrypt_and_add_payload(
            bx_block)

        compressed_size = len(bx_block)
        encrypted_size = len(encrypted_block)

        encryption_details = "Encryption: {}; Size change: {}->{}bytes, {}".format(
            stats_format.timespan(encrypt_start_timestamp, time.time()),
            compressed_size, encrypted_size,
            stats_format.ratio(encrypted_size, compressed_size))

        block_stats.add_block_event_by_block_hash(
            block_hash,
            BlockStatEventType.BLOCK_ENCRYPTED,
            start_date_time=encrypt_start_datetime,
            end_date_time=datetime.datetime.utcnow(),
            network_num=self._node.network_num,
            matching_block_hash=convert.bytes_to_hex(raw_cipher_hash),
            matching_block_type=StatBlockType.ENCRYPTED.value,
            more_info=encryption_details)

        cipher_hash = Sha256Hash(raw_cipher_hash)
        broadcast_message = BroadcastMessage(cipher_hash,
                                             self._node.network_num,
                                             is_encrypted=True,
                                             blob=encrypted_block)

        conns = self._node.broadcast(
            broadcast_message,
            connection,
            connection_types=[ConnectionType.RELAY_BLOCK])

        handling_duration = self._node.track_block_from_node_handling_ended(
            block_hash)
        block_stats.add_block_event_by_block_hash(
            cipher_hash,
            BlockStatEventType.ENC_BLOCK_SENT_FROM_GATEWAY_TO_NETWORK,
            network_num=self._node.network_num,
            requested_by_peer=requested_by_peer,
            peers=conns,
            more_info="Peers: {}; {}; {}; Requested by peer: {}; Handled in {}"
            .format(stats_format.connections(conns), encryption_details,
                    self._format_block_info_stats(block_info),
                    requested_by_peer,
                    stats_format.duration(handling_duration)))
        self.register_for_block_receipts(cipher_hash, bx_block)
        return broadcast_message
    def msg_compressed_block_txs(self, msg: CompressedBlockTxsMessage):
        start_time = time.time()

        self.msg_txs(msg.to_txs_message(),
                     RecoveredTxsSource.COMPRESSED_BLOCK_TXS_RECEIVED)

        block_stats.add_block_event_by_block_hash(
            msg.block_hash(),
            BlockStatEventType.ENC_BLOCK_COMPRESSED_TXS_RECEIVED_BY_GATEWAY,
            network_num=msg.network_num(),
            peers=[self],
            more_info="{}. processing time: {}".format(
                stats_format.connection(self),
                stats_format.timespan(start_time, time.time())))
Exemple #4
0
    def process_block_key(self, msg,
                          connection: AbstractRelayConnection) -> None:
        """
        Handles key message receive from bloXroute.
        Looks for the encrypted block and decrypts; otherwise stores for later.
        """
        key = msg.key()
        block_hash = msg.block_hash()

        if not self._node.should_process_block_hash(block_hash):
            return

        block_stats.add_block_event_by_block_hash(
            block_hash,
            BlockStatEventType.ENC_BLOCK_KEY_RECEIVED_BY_GATEWAY_FROM_NETWORK,
            network_num=connection.network_num,
            peers=[connection])

        if self._node.in_progress_blocks.has_encryption_key_for_hash(
                block_hash):
            return

        if self._node.in_progress_blocks.has_ciphertext_for_hash(block_hash):
            connection.log_trace(
                "Cipher text found. Decrypting and sending to node.")
            decrypt_start_timestamp = time.time()
            decrypt_start_datetime = datetime.datetime.utcnow()
            block = self._node.in_progress_blocks.decrypt_and_get_payload(
                block_hash, key)

            if block is not None:
                block_stats.add_block_event_by_block_hash(
                    block_hash,
                    BlockStatEventType.ENC_BLOCK_DECRYPTED_SUCCESS,
                    start_date_time=decrypt_start_datetime,
                    end_date_time=datetime.datetime.utcnow(),
                    network_num=connection.network_num,
                    more_info=stats_format.timespan(decrypt_start_timestamp,
                                                    time.time()))
                self._handle_decrypted_block(
                    block,
                    connection,
                    encrypted_block_hash_hex=convert.bytes_to_hex(
                        block_hash.binary))
            else:
                block_stats.add_block_event_by_block_hash(
                    block_hash,
                    BlockStatEventType.ENC_BLOCK_DECRYPTION_ERROR,
                    network_num=connection.network_num)
        else:
            connection.log_trace(
                "No cipher text found on key message. Storing.")
            self._node.in_progress_blocks.add_key(block_hash, key)

        conns = self._node.broadcast(
            msg, connection, connection_types=(ConnectionType.GATEWAY, ))
        if len(conns) > 0:
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.ENC_BLOCK_KEY_SENT_BY_GATEWAY_TO_PEERS,
                network_num=self._node.network_num,
                peers=conns)
Exemple #5
0
    def process_block_broadcast(self, msg,
                                connection: AbstractRelayConnection) -> None:
        """
        Handle broadcast message receive from bloXroute.
        This is typically an encrypted block.
        """

        # TODO handle the situation where txs that received from relays while syncing are in the blocks that were
        #  ignored while syncing, so these txs won't be cleaned for 3 days
        if not self._node.should_process_block_hash(msg.block_hash()):
            return

        block_stats.add_block_event(
            msg,
            BlockStatEventType.ENC_BLOCK_RECEIVED_BY_GATEWAY_FROM_NETWORK,
            network_num=connection.network_num,
            more_info=stats_format.connection(connection))

        block_hash = msg.block_hash()
        is_encrypted = msg.is_encrypted()
        self._node.track_block_from_bdn_handling_started(
            block_hash, connection.peer_desc)

        if not is_encrypted:
            block = msg.blob()
            self._handle_decrypted_block(block, connection)
            return

        cipherblob = msg.blob()
        expected_hash = Sha256Hash(crypto.double_sha256(cipherblob))
        if block_hash != expected_hash:
            connection.log_warning(log_messages.BLOCK_WITH_INCONSISTENT_HASHES,
                                   expected_hash, block_hash)
            return

        if self._node.in_progress_blocks.has_encryption_key_for_hash(
                block_hash):
            connection.log_trace(
                "Already had key for received block. Sending block to node.")
            decrypt_start_timestamp = time.time()
            decrypt_start_datetime = datetime.datetime.utcnow()
            block = self._node.in_progress_blocks.decrypt_ciphertext(
                block_hash, cipherblob)

            if block is not None:
                block_stats.add_block_event(
                    msg,
                    BlockStatEventType.ENC_BLOCK_DECRYPTED_SUCCESS,
                    start_date_time=decrypt_start_datetime,
                    end_date_time=datetime.datetime.utcnow(),
                    network_num=connection.network_num,
                    more_info=stats_format.timespan(decrypt_start_timestamp,
                                                    time.time()))
                self._handle_decrypted_block(
                    block,
                    connection,
                    encrypted_block_hash_hex=convert.bytes_to_hex(
                        block_hash.binary))
            else:
                block_stats.add_block_event(
                    msg,
                    BlockStatEventType.ENC_BLOCK_DECRYPTION_ERROR,
                    network_num=connection.network_num)
        else:
            connection.log_trace("Received encrypted block. Storing.")
            self._node.in_progress_blocks.add_ciphertext(
                block_hash, cipherblob)
            block_received_message = BlockReceivedMessage(block_hash)
            conns = self._node.broadcast(
                block_received_message,
                connection,
                connection_types=(ConnectionType.GATEWAY, ))
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.ENC_BLOCK_SENT_BLOCK_RECEIPT,
                network_num=connection.network_num,
                peers=conns,
            )