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)
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())))
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)
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, )