def bx_block_to_block(self, bx_block_msg, tx_service) -> BlockDecompressionResult:
        """
        Uncompresses a bx_block from a broadcast bx_block message and converts to a raw BTC bx_block.

        bx_block must be a memoryview, since memoryview[offset] returns a bytearray, while bytearray[offset] returns
        a byte.
        """
        if not isinstance(bx_block_msg, memoryview):
            bx_block_msg = memoryview(bx_block_msg)

        decompress_start_datetime = datetime.utcnow()
        decompress_start_timestamp = time.time()

        # Initialize tracking of transaction and SID mapping
        block_pieces = deque()
        header_info = parse_bx_block_header(bx_block_msg, block_pieces)
        unknown_tx_sids, unknown_tx_hashes, offset = parse_bx_block_transactions(
            header_info.block_hash,
            bx_block_msg,
            header_info.offset,
            header_info.short_ids,
            header_info.block_offsets,
            tx_service,
            block_pieces
        )
        total_tx_count = header_info.txn_count

        if not unknown_tx_sids and not unknown_tx_hashes:
            btc_block_msg, offset = build_btc_block(block_pieces, offset)
            logger.debug(
                "Successfully parsed block broadcast message. {} transactions "
                "in block {}",
                total_tx_count,
                header_info.block_hash
            )
        else:
            btc_block_msg = None
            logger.debug(
                "Block recovery needed for {}. Missing {} sids, {} tx hashes. "
                "Total txs in block: {}",
                header_info.block_hash,
                len(unknown_tx_sids),
                len(unknown_tx_hashes),
                total_tx_count
            )
        block_info = get_block_info(
            bx_block_msg,
            header_info.block_hash,
            header_info.short_ids,
            decompress_start_datetime,
            decompress_start_timestamp,
            total_tx_count,
            btc_block_msg
        )
        return BlockDecompressionResult(btc_block_msg, block_info, unknown_tx_sids, unknown_tx_hashes)
 def bx_block_to_block(self, bx_block_msg, tx_service) -> BlockDecompressionResult:
     decompress_start_datetime = datetime.utcnow()
     decompress_start_timestamp = time.time()
     tsk = self.decompression_tasks.borrow_task()
     tsk.init(tpe.InputBytes(bx_block_msg), tx_service.proxy)
     try:
         task_pool_proxy.run_task(tsk)
     except tpe.AggregatedException as e:
         self.decompression_tasks.return_task(tsk)
         header_info = btc_normal_message_converter.parse_bx_block_header(bx_block_msg, deque())
         raise message_conversion_error.btc_block_decompression_error(header_info.block_hash, e)
     total_tx_count = tsk.tx_count()
     unknown_tx_hashes = [Sha256Hash(bytearray(unknown_tx_hash.binary()))
                          for unknown_tx_hash in tsk.unknown_tx_hashes()]
     unknown_tx_sids = tsk.unknown_tx_sids()
     block_hash = BtcObjectHash(
         binary=convert.hex_to_bytes(tsk.block_hash().hex_string())
     )
     if tsk.success():
         btc_block_msg = BlockBtcMessage(buf=memoryview(tsk.block_message()))
         logger.debug(
             "Successfully parsed block broadcast message. {} transactions "
             "in block {}",
             total_tx_count,
             block_hash
         )
     else:
         btc_block_msg = None
         logger.debug(
             "Block recovery needed for {}. Missing {} sids, {} tx hashes. "
             "Total txs in block: {}",
             block_hash,
             len(unknown_tx_sids),
             len(unknown_tx_hashes),
             total_tx_count
         )
     block_info = get_block_info(
         bx_block_msg,
         block_hash,
         tsk.short_ids(),
         decompress_start_datetime,
         decompress_start_timestamp,
         total_tx_count,
         btc_block_msg
     )
     self.decompression_tasks.return_task(tsk)
     return BlockDecompressionResult(btc_block_msg, block_info, unknown_tx_sids, unknown_tx_hashes)
    def bx_block_to_block(
            self, bx_block_msg: memoryview,
            tx_service: TransactionService) -> BlockDecompressionResult:
        """
        Uncompresses a bx_block from a broadcast bx_block message and converts to a raw Ontology bx_block.

        bx_block must be a memoryview, since memoryview[offset] returns a bytearray, while bytearray[offset] returns
        a byte.
        """
        # pyre-fixme[25]: Assertion will always fail.
        if not isinstance(bx_block_msg, memoryview):
            bx_block_msg = memoryview(bx_block_msg)

        decompress_start_datetime = datetime.utcnow()
        decompress_start_timestamp = time.time()

        # Initialize tracking of transaction and SID mapping
        block_pieces = deque()
        header_info = parse_bx_block_header(bx_block_msg, block_pieces)
        unknown_tx_sids, unknown_tx_hashes, offset = parse_bx_block_transactions(
            header_info.block_hash, bx_block_msg, header_info.offset,
            header_info.short_ids, header_info.block_offsets, tx_service,
            block_pieces)
        total_tx_count = header_info.txn_count

        if not unknown_tx_sids and not unknown_tx_hashes:
            ont_block_msg, offset = build_ont_block(block_pieces, offset)
            logger.debug(
                "Successfully parsed bx_block broadcast message. {} transactions in bx_block",
                total_tx_count)
        else:
            ont_block_msg = None
            logger.warning(log_messages.BLOCK_RECOVERY_NEEDED,
                           len(unknown_tx_sids), len(unknown_tx_hashes),
                           total_tx_count)
        block_info = get_block_info(bx_block_msg, header_info.block_hash,
                                    header_info.short_ids,
                                    decompress_start_datetime,
                                    decompress_start_timestamp, total_tx_count,
                                    ont_block_msg)
        return BlockDecompressionResult(ont_block_msg, block_info,
                                        unknown_tx_sids, unknown_tx_hashes)
Exemple #4
0
    def bx_block_to_block(self, bx_block_msg: memoryview, tx_service: TransactionService) -> BlockDecompressionResult:
        start_datetime = datetime.utcnow()
        start_time = time.time()

        block_msg = BlockOntMessage(buf=bytearray(bx_block_msg))

        block_info = BlockInfo(
            block_msg.block_hash(),
            [],
            start_datetime,
            datetime.utcnow(),
            (time.time() - start_time) * 1000,
            block_msg.txn_count(),
            str(block_msg.block_hash()),
            convert.bytes_to_hex(block_msg.prev_block_hash().binary),
            len(block_msg.rawbytes()),
            len(block_msg.rawbytes()),
            0
        )
        return BlockDecompressionResult(block_msg, block_info, [], [])
    def bx_block_to_block(self, bx_block_msg, tx_service) -> BlockDecompressionResult:
        start_datetime = datetime.datetime.utcnow()
        start_time = time.time()
        block_msg = BlockBtcMessage(buf=bx_block_msg)

        block_info = BlockInfo(
            block_msg.block_hash(),
            [],
            start_datetime,
            datetime.datetime.utcnow(),
            (time.time() - start_time) * 1000,
            block_msg.txn_count(),
            # pyre-fixme[6]: Expected `Optional[str]` for 7th param but got
            #  `BtcObjectHash`.
            block_msg.block_hash(),
            convert.bytes_to_hex(block_msg.prev_block_hash().binary),
            len(block_msg.rawbytes()),
            len(block_msg.rawbytes()),
            0
        )
        return BlockDecompressionResult(block_msg, block_info, [], [])
Exemple #6
0
    def bx_block_to_block(self, bx_block_msg,
                          tx_service) -> BlockDecompressionResult:
        """
        Converts internal broadcast message to Ethereum new block message

        The code is optimized and does not make copies of bytes

        :param bx_block_msg: internal broadcast message bytes
        :param tx_service: Transactions service
        :return: tuple (new block message, block hash, unknown transaction short id, unknown transaction hashes)
        """

        if not isinstance(bx_block_msg, (bytearray, memoryview)):
            raise TypeError(
                "Type bytearray is expected for arg block_bytes but was {0}".
                format(type(bx_block_msg)))

        decompress_start_datetime = datetime.datetime.utcnow()
        decompress_start_timestamp = time.time()

        block_msg_bytes = bx_block_msg if isinstance(
            bx_block_msg, memoryview) else memoryview(bx_block_msg)

        block_offsets = compact_block_short_ids_serializer.get_bx_block_offsets(
            bx_block_msg)
        short_ids, short_ids_bytes_len = compact_block_short_ids_serializer.deserialize_short_ids_from_buffer(
            bx_block_msg, block_offsets.short_id_offset)

        block_bytes = block_msg_bytes[
            block_offsets.block_begin_offset:block_offsets.short_id_offset]

        _, block_itm_len, block_itm_start = rlp_utils.consume_length_prefix(
            block_bytes, 0)
        block_itm_bytes = block_bytes[block_itm_start:]

        _, block_hdr_len, block_hdr_start = rlp_utils.consume_length_prefix(
            block_itm_bytes, 0)
        full_hdr_bytes = block_itm_bytes[0:block_hdr_start + block_hdr_len]

        block_hash_bytes = eth_common_utils.keccak_hash(full_hdr_bytes)
        block_hash = Sha256Hash(block_hash_bytes)

        _, block_txs_len, block_txs_start = rlp_utils.consume_length_prefix(
            block_itm_bytes, block_hdr_start + block_hdr_len)
        txs_bytes = block_itm_bytes[block_txs_start:block_txs_start +
                                    block_txs_len]

        remaining_bytes = block_itm_bytes[block_txs_start + block_txs_len:]

        # parse statistics variables
        short_tx_index = 0
        unknown_tx_sids = []
        unknown_tx_hashes = []

        # creating transactions content
        content_size = 0
        buf = deque()
        tx_count = 0

        tx_start_index = 0

        while True:
            if tx_start_index >= len(txs_bytes):
                break

            _, tx_itm_len, tx_itm_start = rlp_utils.consume_length_prefix(
                txs_bytes, tx_start_index)
            tx_bytes = txs_bytes[tx_itm_start:tx_itm_start + tx_itm_len]

            is_full_tx_start = 0
            is_full_tx, is_full_tx_len, = rlp_utils.decode_int(
                tx_bytes, is_full_tx_start)

            _, tx_content_len, tx_content_start = rlp_utils.consume_length_prefix(
                tx_bytes, is_full_tx_start + is_full_tx_len)
            tx_content_bytes = tx_bytes[tx_content_start:tx_content_start +
                                        tx_content_len]
            if is_full_tx:
                tx_bytes = tx_content_bytes
            else:
                short_id = short_ids[short_tx_index]
                tx_hash, tx_bytes, _ = tx_service.get_transaction(short_id)

                if tx_hash is None:
                    unknown_tx_sids.append(short_id)
                elif tx_bytes is None:
                    unknown_tx_hashes.append(tx_hash)

                short_tx_index += 1

            if tx_bytes is not None and not unknown_tx_sids and not unknown_tx_hashes:
                buf.append(tx_bytes)
                content_size += len(tx_bytes)

            tx_count += 1

            tx_start_index = tx_itm_start + tx_itm_len

        if not unknown_tx_sids and not unknown_tx_hashes:

            txs_prefix = rlp_utils.get_length_prefix_list(content_size)
            buf.appendleft(txs_prefix)
            content_size += len(txs_prefix)

            buf.appendleft(full_hdr_bytes)
            content_size += len(full_hdr_bytes)

            buf.append(remaining_bytes)
            content_size += len(remaining_bytes)

            msg_len_prefix = rlp_utils.get_length_prefix_list(content_size)
            buf.appendleft(msg_len_prefix)

            block_msg_bytes = bytearray(content_size)
            off = 0
            for blob in buf:
                next_off = off + len(blob)
                block_msg_bytes[off:next_off] = blob
                off = next_off

            block_msg = InternalEthBlockInfo(block_msg_bytes)
            logger.debug(
                "Successfully parsed block broadcast message. {} "
                "transactions in block {}", tx_count, block_hash)

            bx_block_hash = convert.bytes_to_hex(
                crypto.double_sha256(bx_block_msg))
            compressed_size = len(bx_block_msg)

            block_info = BlockInfo(
                block_hash, short_ids, decompress_start_datetime,
                datetime.datetime.utcnow(),
                (time.time() - decompress_start_timestamp) * 1000, tx_count,
                bx_block_hash,
                convert.bytes_to_hex(block_msg.prev_block_hash().binary),
                len(block_msg.rawbytes()), compressed_size,
                100 - float(compressed_size) / content_size * 100, [])

            return BlockDecompressionResult(block_msg, block_info,
                                            unknown_tx_sids, unknown_tx_hashes)
        else:
            logger.debug(
                "Block recovery needed for {}. Missing {} sids, {} tx hashes. "
                "Total txs in block: {}", block_hash, len(unknown_tx_sids),
                len(unknown_tx_hashes), tx_count)

            return BlockDecompressionResult(
                None,
                BlockInfo(block_hash, short_ids, decompress_start_datetime,
                          datetime.datetime.utcnow(),
                          (time.time() - decompress_start_timestamp) * 1000,
                          None, None, None, None, None, None, []),
                unknown_tx_sids, unknown_tx_hashes)
Exemple #7
0
 def bx_block_to_block(self, bx_block_msg,
                       tx_service) -> BlockDecompressionResult:
     block_message = MockBlockMessage(buf=bx_block_msg)
     return BlockDecompressionResult(block_message,
                                     block_message.block_hash(), [], [])
Exemple #8
0
    def bx_block_to_block(self, bx_block_msg,
                          tx_service) -> BlockDecompressionResult:
        decompress_start_datetime = datetime.datetime.utcnow()
        decompress_start_timestamp = time.time()
        tsk = self.decompression_tasks.borrow_task()
        tsk.init(tpe.InputBytes(bx_block_msg), tx_service.proxy)
        try:
            task_pool_proxy.run_task(tsk)
        except tpe.AggregatedException as e:
            block_hash = Sha256Hash(
                convert.hex_to_bytes(tsk.block_hash().hex_string()))
            self.decompression_tasks.return_task(tsk)
            # TODO find a better solution
            raise message_conversion_error.eth_block_decompression_error(
                block_hash, e)

        total_tx_count = tsk.tx_count()
        unknown_tx_hashes = [
            Sha256Hash(bytearray(unknown_tx_hash.binary()))
            for unknown_tx_hash in tsk.unknown_tx_hashes()
        ]
        unknown_tx_sids = tsk.unknown_tx_sids()
        block_hash = Sha256Hash(
            convert.hex_to_bytes(tsk.block_hash().hex_string()))

        if tsk.success():
            starting_offset = tsk.starting_offset()
            block = memoryview(tsk.block_message())[starting_offset:]
            block_msg = InternalEthBlockInfo(block)
            content_size = len(block_msg.rawbytes())
            logger.debug(
                "Successfully parsed block broadcast message. {} "
                "transactions in block {}", total_tx_count, block_hash)
            bx_block_hash = convert.bytes_to_hex(
                crypto.double_sha256(bx_block_msg))
            compressed_size = len(bx_block_msg)

            block_info = BlockInfo(
                block_hash, tsk.short_ids(), decompress_start_datetime,
                datetime.datetime.utcnow(),
                (time.time() - decompress_start_timestamp) * 1000,
                total_tx_count, bx_block_hash,
                convert.bytes_to_hex(block_msg.prev_block_hash().binary),
                len(block_msg.rawbytes()), compressed_size,
                100 - float(compressed_size) / content_size * 100)
        else:
            block_msg = None

            logger.debug(
                "Block recovery needed for {}. Missing {} sids, {} tx hashes. "
                "Total txs in block: {}", block_hash, len(unknown_tx_sids),
                len(unknown_tx_hashes), total_tx_count)
            block_info = BlockInfo(
                block_hash, tsk.short_ids(), decompress_start_datetime,
                datetime.datetime.utcnow(),
                (time.time() - decompress_start_timestamp) * 1000, None, None,
                None, None, None, None)

        self.decompression_tasks.return_task(tsk)
        return BlockDecompressionResult(block_msg, block_info, unknown_tx_sids,
                                        unknown_tx_hashes)