예제 #1
0
    def try_calculate_total_difficulty(
            self, block_hash: Sha256Hash,
            new_block_parts: NewBlockParts) -> Optional[int]:
        previous_block_hash = new_block_parts.get_previous_block_hash()
        previous_block_total_difficulty = None

        for known_block_hash, known_total_difficulty in self._last_known_difficulties:
            if previous_block_hash == known_block_hash:
                previous_block_total_difficulty = known_total_difficulty
                break

        if previous_block_total_difficulty is None:
            logger.debug(
                "Unable to calculate total difficulty after block {}.",
                convert.bytes_to_hex(block_hash.binary))
            return None

        block_total_difficulty = previous_block_total_difficulty + new_block_parts.get_block_difficulty(
        )

        self._last_known_difficulties.append(
            (block_hash, block_total_difficulty))
        logger.debug("Calculated total difficulty after block {} = {}.",
                     convert.bytes_to_hex(block_hash.binary),
                     block_total_difficulty)

        return block_total_difficulty
예제 #2
0
def get_block_info(
        bx_block: memoryview,
        block_hash: Sha256Hash,
        short_ids: List[int],
        decompress_start_datetime: datetime,
        decompress_start_timestamp: float,
        total_tx_count: Optional[int] = None,
        btc_block_msg: Optional[BlockBtcMessage] = None
) -> BlockInfo:
    if btc_block_msg is not None:
        bx_block_hash = convert.bytes_to_hex(crypto.double_sha256(bx_block))
        compressed_size = len(bx_block)
        prev_block_hash = convert.bytes_to_hex(btc_block_msg.prev_block_hash().binary)
        btc_block_len = len(btc_block_msg.rawbytes())
        compression_rate = 100 - float(compressed_size) / btc_block_len * 100
    else:
        bx_block_hash = None
        compressed_size = None
        prev_block_hash = None
        btc_block_len = None
        compression_rate = None
    return BlockInfo(
        block_hash,
        short_ids,
        decompress_start_datetime,
        datetime.utcnow(),
        (time.time() - decompress_start_timestamp) * 1000,
        total_tx_count,
        bx_block_hash,
        prev_block_hash,
        btc_block_len,
        compressed_size,
        compression_rate
    )
예제 #3
0
    def test_set_contents(self):
        transaction_hash = Sha256Hash(
            helpers.generate_bytearray(crypto.SHA256_HASH_LEN))
        transaction_key = self.transaction_service.get_transaction_key(
            transaction_hash)
        tx_contents = memoryview(helpers.generate_bytearray(500))

        self.assertFalse(
            self.transaction_service.has_transaction_contents_by_key(
                transaction_key))

        self.transaction_service.set_transaction_contents_by_key(
            transaction_key, tx_contents)

        self.assertTrue(
            self.transaction_service.has_transaction_contents_by_key(
                transaction_key))

        saved_contents = self.transaction_service.get_transaction_by_key(
            transaction_key)
        self.assertEqual(convert.bytes_to_hex(tx_contents),
                         convert.bytes_to_hex(saved_contents.tobytes()))
        self.assertEqual(len(tx_contents),
                         self.transaction_service._total_tx_contents_size)

        new_content = memoryview(helpers.generate_bytearray(750))
        self.transaction_service.set_transaction_contents_by_key(
            transaction_key, new_content)
        saved_contents = self.transaction_service.get_transaction_by_key(
            transaction_key)
        self.assertEqual(convert.bytes_to_hex(tx_contents),
                         convert.bytes_to_hex(saved_contents.tobytes()))
        self.assertEqual(len(new_content),
                         self.transaction_service._total_tx_contents_size)
예제 #4
0
    def start_transaction_recovery(
            self,
            unknown_sids: Iterable[int],
            unknown_hashes: Iterable[Sha256Hash],
            block_hash: Sha256Hash,
            connection: Optional[AbstractRelayConnection] = None) -> None:
        all_unknown_sids = []
        all_unknown_sids.extend(unknown_sids)
        tx_service = self._node.get_tx_service()

        # retrieving sids of txs with unknown contents
        for tx_hash in unknown_hashes:
            transaction_key = tx_service.get_transaction_key(tx_hash)
            tx_sid = tx_service.get_short_id_by_key(transaction_key)
            all_unknown_sids.append(tx_sid)

        if not self._node.opts.request_recovery:
            if connection is not None:
                network_num = connection.network_num
            else:
                network_num = self._node.network_num
            # log recovery started to match with recovery completing
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.BLOCK_RECOVERY_STARTED,
                network_num=network_num,
                txs_count=len(all_unknown_sids),
                more_info="recovery from relay is disabled",
            )
            return

        get_txs_message = GetTxsMessage(short_ids=all_unknown_sids)
        self._node.broadcast(
            get_txs_message,
            connection_types=(ConnectionType.RELAY_TRANSACTION, ))

        if connection is not None:
            tx_stats.add_txs_by_short_ids_event(
                all_unknown_sids,
                TransactionStatEventType.
                TX_UNKNOWN_SHORT_IDS_REQUESTED_BY_GATEWAY_FROM_RELAY,
                network_num=self._node.network_num,
                peers=[connection],
                block_hash=convert.bytes_to_hex(block_hash.binary))
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.BLOCK_RECOVERY_STARTED,
                network_num=connection.network_num,
                txs_count=len(all_unknown_sids),
                request_hash=convert.bytes_to_hex(
                    crypto.double_sha256(get_txs_message.rawbytes())))
        else:
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.BLOCK_RECOVERY_REPEATED,
                network_num=self._node.network_num,
                txs_count=len(all_unknown_sids),
                request_hash=convert.bytes_to_hex(
                    crypto.double_sha256(get_txs_message.rawbytes())))
    def block_to_bx_block(
            self, block_msg, tx_service
    ) -> Tuple[memoryview, BlockInfo]:
        """
        Compresses a Bitcoin block's transactions and packs it into a bloXroute block.
        """
        compress_start_datetime = datetime.utcnow()
        compress_start_timestamp = time.time()
        size = 0
        buf = deque()
        short_ids = []
        header = block_msg.header()
        size += len(header)
        buf.append(header)

        for tx in block_msg.txns():

            tx_hash = btc_common_utils.get_txid(tx)
            short_id = tx_service.get_short_id(tx_hash)
            if short_id == constants.NULL_TX_SID:
                buf.append(tx)
                size += len(tx)
            else:
                short_ids.append(short_id)
                buf.append(btc_constants.BTC_SHORT_ID_INDICATOR_AS_BYTEARRAY)
                size += 1

        serialized_short_ids = compact_block_short_ids_serializer.serialize_short_ids_into_bytes(short_ids)
        buf.append(serialized_short_ids)
        size += constants.UL_ULL_SIZE_IN_BYTES
        offset_buf = struct.pack("<Q", size)
        buf.appendleft(offset_buf)
        size += len(serialized_short_ids)

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

        prev_block_hash = convert.bytes_to_hex(block_msg.prev_block_hash().binary)
        bx_block_hash = convert.bytes_to_hex(crypto.double_sha256(block))
        original_size = len(block_msg.rawbytes())

        block_info = BlockInfo(
            block_msg.block_hash(),
            short_ids,
            compress_start_datetime,
            datetime.utcnow(),
            (time.time() - compress_start_timestamp) * 1000,
            block_msg.txn_count(),
            bx_block_hash,
            prev_block_hash,
            original_size,
            size,
            100 - float(size) / original_size * 100
        )
        return memoryview(block), block_info
예제 #6
0
 def _safe_decrypt_item(self, cache_item, hash_key):
     try:
         return cache_item.decrypt()
     except DecryptionError:
         failed_ciphertext = self.pop_ciphertext(hash_key)
         logger.warning(log_messages.DECRYPTION_FAILED,
                        convert.bytes_to_hex(hash_key), convert.bytes_to_hex(failed_ciphertext[-4:]))
         return None
    def block_to_bx_block(
            self, block_msg, tx_service, enable_block_compression: bool,
            min_tx_age_seconds: float) -> Tuple[memoryview, BlockInfo]:
        """
        Compresses a Bitcoin block's transactions and packs it into a bloXroute block.
        """
        compress_start_datetime = datetime.utcnow()
        compress_start_timestamp = time.time()
        size = 0
        buf = deque()
        short_ids = []
        original_size = len(block_msg.rawbytes())
        ignored_sids = []

        header = block_msg.header()
        size += len(header)
        buf.append(header)

        max_timestamp_for_compression = time.time() - min_tx_age_seconds

        for tx in block_msg.txns():
            tx_hash = btc_common_utils.get_txid(tx)
            transaction_key = tx_service.get_transaction_key(tx_hash)
            short_id = tx_service.get_short_id_by_key(transaction_key)

            short_id_assign_time = 0
            if short_id != constants.NULL_TX_SID:
                short_id_assign_time = tx_service.get_short_id_assign_time(
                    short_id)

            if short_id == constants.NULL_TX_SID or \
                    not enable_block_compression or \
                    short_id_assign_time > max_timestamp_for_compression:
                if short_id != constants.NULL_TX_SIDS:
                    ignored_sids.append(short_id)
                buf.append(tx)
                size += len(tx)
            else:
                short_ids.append(short_id)
                buf.append(btc_constants.BTC_SHORT_ID_INDICATOR_AS_BYTEARRAY)
                size += 1

        block = finalize_block_bytes(buf, size, short_ids)

        prev_block_hash = convert.bytes_to_hex(
            block_msg.prev_block_hash().binary)
        bx_block_hash = convert.bytes_to_hex(crypto.double_sha256(block))

        block_info = BlockInfo(block_msg.block_hash(), short_ids,
                               compress_start_datetime, datetime.utcnow(),
                               (time.time() - compress_start_timestamp) * 1000,
                               block_msg.txn_count(), bx_block_hash,
                               prev_block_hash, original_size, size,
                               100 - float(size) / original_size * 100,
                               ignored_sids)

        return memoryview(block), block_info
예제 #8
0
 def _safe_decrypt_item(self, cache_item, hash_key):
     try:
         return cache_item.decrypt()
     except DecryptionError:
         failed_ciphertext = self.pop_ciphertext(hash_key)
         logger.warning(
             "Could not decrypt encrypted item with hash {}. Last four bytes: {}",
             convert.bytes_to_hex(hash_key),
             convert.bytes_to_hex(failed_ciphertext[-4:]))
         return None
예제 #9
0
 def _check_end_result(self, et, plain):
     k = bytes(bytearray(et.key()))
     c = bytes(bytearray(et.cipher()))
     try:
         self.assertEqual(SecretBox(k).decrypt(c), plain)
     except CryptoError as e:
         self.fail("failed to decrypt cipher: {}, with key: {}, "
                   "for plain: {}\n{}".format(bytes_to_hex(c),
                                              bytes_to_hex(k),
                                              bytes_to_hex(plain), e))
예제 #10
0
    def _get_last_msg_bytes(self, msg, input_buffer_len_before, payload_len):

        if msg is not None:
            return convert.bytes_to_hex(msg.rawbytes()[:constants.MAX_LOGGED_BYTES_LEN])

        # bytes still available on input buffer
        if input_buffer_len_before == self.inputbuf.length and payload_len is not None:
            return convert.bytes_to_hex(
                self.inputbuf.peek_message(min(self.header_size + payload_len, constants.MAX_LOGGED_BYTES_LEN)))

        return "<not available>"
예제 #11
0
    def test_int_to_big_endian(self):
        big_endian_0 = rlp_utils.int_to_big_endian(0)
        self.assertEqual(b"\x00", big_endian_0)

        big_endian_1 = rlp_utils.int_to_big_endian(1)
        self.assertEqual("01", convert.bytes_to_hex(big_endian_1))

        big_endian_1025 = rlp_utils.int_to_big_endian(1025)
        self.assertEqual("0401", convert.bytes_to_hex(big_endian_1025))

        big_endian_133124 = rlp_utils.int_to_big_endian(133124)
        self.assertEqual("020804", convert.bytes_to_hex(big_endian_133124))
예제 #12
0
    def _tx_hash_to_cache_key(self, transaction_hash: Union[Sha256Hash, bytes, bytearray, memoryview, str]) \
            -> str:

        if isinstance(transaction_hash, Sha256Hash):
            return convert.bytes_to_hex(transaction_hash.binary)

        if isinstance(transaction_hash, (bytes, bytearray, memoryview)):
            return convert.bytes_to_hex(transaction_hash)

        if isinstance(transaction_hash, str):
            return transaction_hash

        raise ValueError(
            "Attempted to find cache entry with incorrect key type")
예제 #13
0
    def test_new_block_internal_eth_message_to_from_new_block_message(self):
        txs = []
        txs_bytes = []
        txs_hashes = []

        tx_count = 10

        for i in range(1, tx_count):
            tx = mock_eth_messages.get_dummy_transaction(1)
            txs.append(tx)

            tx_bytes = rlp.encode(tx, Transaction)
            txs_bytes.append(tx_bytes)

            tx_hash = tx.hash()
            txs_hashes.append(tx_hash)

        block_header = mock_eth_messages.get_dummy_block_header(1)

        uncles = [
            mock_eth_messages.get_dummy_block_header(2),
            mock_eth_messages.get_dummy_block_header(3),
        ]

        block = Block(block_header, txs, uncles)

        dummy_chain_difficulty = 10

        block_msg = NewBlockEthProtocolMessage(None, block,
                                               dummy_chain_difficulty)
        self.assertTrue(block_msg.rawbytes())

        new_block_internal_eth_msg = InternalEthBlockInfo.from_new_block_msg(
            block_msg)
        self.assertIsNotNone(new_block_internal_eth_msg)
        self.assertTrue(new_block_internal_eth_msg.rawbytes())

        parsed_new_block_message = new_block_internal_eth_msg.to_new_block_msg(
        )
        self.assertIsInstance(parsed_new_block_message,
                              NewBlockEthProtocolMessage)

        self.assertEqual(len(block_msg.rawbytes()),
                         len(parsed_new_block_message.rawbytes()))
        self.assertEqual(
            convert.bytes_to_hex(block_msg.rawbytes()),
            convert.bytes_to_hex(parsed_new_block_message.rawbytes()),
        )
예제 #14
0
    async def test_transaction_status(self):
        time.time = MagicMock(return_value=time.time())
        expected_assignment_time = datetime.datetime.fromtimestamp(
            time.time()).isoformat()

        short_id = 123
        transaction_hash = helpers.generate_object_hash()
        transaction_contents = helpers.generate_bytearray(250)

        tx_service = self.gateway_node.get_tx_service()
        transaction_key = tx_service.get_transaction_key(transaction_hash)
        tx_service.set_transaction_contents_by_key(transaction_key,
                                                   transaction_contents)
        tx_service.assign_short_id_by_key(transaction_key, short_id)

        result = await self.request(
            BxJsonRpcRequest("7", RpcRequestType.TX_STATUS, {
                "transaction_hash":
                convert.bytes_to_hex(transaction_hash.binary)
            }))
        self.assertEqual("7", result.id)
        self.assertIsNone(result.error)
        self.assertEqual(
            {
                "status": "assigned short ID",
                "short_ids": [123],
                "assignment_time": expected_assignment_time
            }, result.result)
예제 #15
0
    def add_block_event(self,
                        block_msg,
                        block_event_settings,
                        network_num,
                        start_date_time=None,
                        end_date_time=None,
                        **kwargs):
        if not self._should_log_stat_event(block_event_settings):
            return

        if isinstance(block_msg, BroadcastMessage):
            block_hash = block_msg.block_hash().binary
        elif isinstance(block_msg, memoryview):
            block_hash = block_msg[BX_HDR_COMMON_OFF:BX_HDR_COMMON_OFF +
                                   crypto.SHA256_HASH_LEN].tobytes()
        else:
            block_hash = block_msg[BX_HDR_COMMON_OFF:BX_HDR_COMMON_OFF +
                                   crypto.SHA256_HASH_LEN]

        self.log_event(block_event_settings,
                       convert.bytes_to_hex(block_hash),
                       start_date_time,
                       end_date_time,
                       network_num=network_num,
                       **kwargs)
예제 #16
0
    def record_block_receipt(self, cipher_hash, connection):
        """
        Records a receipt of a block hash. Releases key if threshold reached.
        :param cipher_hash encrypted block ObjectHash
        :param connection posting block received receipt
        """
        if cipher_hash in self._receipt_tracker:
            self._receipt_tracker[cipher_hash] += 1
            block_stats.add_block_event_by_block_hash(
                cipher_hash,
                BlockStatEventType.ENC_BLOCK_RECEIVED_BLOCK_RECEIPT,
                network_num=self._node.network_num,
                peers=[connection],
                more_info="{}, {} receipts".format(
                    stats_format.connection(connection),
                    self._receipt_tracker[cipher_hash]))

            if self._are_enough_receipts_received(cipher_hash):
                logger.debug(
                    "Received enough block receipt messages. Releasing key for block with hash: {}",
                    convert.bytes_to_hex(cipher_hash.binary))
                self._send_key(cipher_hash)
                self._node.alarm_queue.unregister_alarm(
                    self._alarms[cipher_hash])
                del self._receipt_tracker[cipher_hash]
                del self._alarms[cipher_hash]
예제 #17
0
 def __init__(
     self,
     hash: Sha256Hash,
     block: memoryview
 ) -> None:
     self.hash = str(hash)
     self.block = convert.bytes_to_hex(block)
예제 #18
0
    def _propagate_block_to_gateway_peers(self, cipher_hash, bx_block):
        """
        Propagates unencrypted bx_block to all gateway peers for encryption and sending to bloXroute.
        Also sends keys to bloXroute in case this was user error (e.g. no gateway peers).
        Called after a timeout. This invalidates all future bx_block receipts.
        """
        bx_block_hash = crypto.double_sha256(bx_block)
        hex_bx_block_hash = convert.bytes_to_hex(bx_block_hash)

        logger.debug("Did not receive enough receipts for: {}. Propagating compressed block to other gateways: {}",
                     cipher_hash, hex_bx_block_hash)
        self._send_key(cipher_hash)

        request = BlockPropagationRequestMessage(bx_block)
        conns = self._node.broadcast(request, None, connection_types=(ConnectionType.GATEWAY,))
        block_stats.add_block_event_by_block_hash(cipher_hash,
                                                  BlockStatEventType.ENC_BLOCK_PROPAGATION_NEEDED,
                                                  network_num=self._node.network_num,
                                                  compressed_block_hash=hex_bx_block_hash,
                                                  peers=conns,
                                                  more_info="Peers: {}, {} receipts".format(
                                                      stats_format.connections(conns),
                                                      self._receipt_tracker[cipher_hash]))

        del self._receipt_tracker[cipher_hash]
        del self._alarms[cipher_hash]
        return constants.CANCEL_ALARMS
예제 #19
0
    def test_block_to_bx_block__empty_block_success(self):
        block = Block(mock_eth_messages.get_dummy_block_header(8), [], [])

        dummy_chain_difficulty = 10

        block_msg = NewBlockEthProtocolMessage(None, block, dummy_chain_difficulty)
        self.assertTrue(block_msg.rawbytes())
        internal_new_block_msg = InternalEthBlockInfo.from_new_block_msg(block_msg)

        bx_block_msg, block_info = self.eth_message_converter.block_to_bx_block(
            internal_new_block_msg, self.tx_service, True, 0
        )

        self.assertEqual(0, block_info.txn_count)
        self.assertEqual(convert.bytes_to_hex(block.header.prev_hash), block_info.prev_block_hash)

        self.assertTrue(bx_block_msg)
        self.assertIsInstance(bx_block_msg, memoryview)

        block_offsets = compact_block_short_ids_serializer.get_bx_block_offsets(bx_block_msg)
        _, short_ids_len = compact_block_short_ids_serializer.deserialize_short_ids_from_buffer(
            bx_block_msg,
            block_offsets.short_id_offset
        )
        compact_block = rlp.decode(
            bx_block_msg[block_offsets.block_begin_offset: block_offsets.short_id_offset].tobytes(),
            CompactBlock
        )
        self.assertTrue(compact_block)
        self.assertIsInstance(compact_block, CompactBlock)

        self._assert_values_equal(compact_block.header, block.header)
        self.assertEqual(0, len(compact_block.uncles))
        self.assertEqual(0, len(compact_block.transactions))
        self.assertEqual(compact_block.chain_difficulty, block_msg.chain_difficulty)
    def msg_block_bodies(self, msg: BlockBodiesEthProtocolMessage):
        if not self.node.should_process_block_hash():
            return

        if self._block_bodies_requests:
            requested_hashes = self._block_bodies_requests.popleft()

            bodies_bytes = msg.get_block_bodies_bytes()

            if len(requested_hashes) != len(bodies_bytes):
                logger.debug(
                    "Expected {} bodies in response but received {}. Proxy message to remote node.",
                    len(requested_hashes), len(bodies_bytes))
                self._block_bodies_requests.clear()
                return

            logger.debug(
                "Processing expected block bodies messages for blocks [{}]",
                ", ".join([
                    convert.bytes_to_hex(block_hash.binary)
                    for block_hash in requested_hashes
                ]))

            for block_hash, block_body_bytes in zip(requested_hashes,
                                                    bodies_bytes):
                if block_hash in self.pending_new_block_parts.contents:
                    logger.debug(
                        "Received block body for pending new block {}",
                        convert.bytes_to_hex(block_hash.binary))
                    self.pending_new_block_parts.contents[
                        block_hash].block_body_bytes = block_body_bytes
                    self._check_pending_new_block(block_hash)
                elif self.node.block_cleanup_service.is_marked_for_cleanup(
                        block_hash):
                    transactions_hashes = \
                        BlockBodiesEthProtocolMessage.from_body_bytes(block_body_bytes).get_block_transaction_hashes(0)
                    # pyre-fixme[16]: `AbstractBlockCleanupService` has no attribute
                    #  `clean_block_transactions_by_block_components`.
                    self.node.block_cleanup_service.clean_block_transactions_by_block_components(
                        transaction_service=self.node.get_tx_service(),
                        block_hash=block_hash,
                        transactions_list=transactions_hashes)
                else:
                    logger.warning(log_messages.REDUNDANT_BLOCK_BODY,
                                   convert.bytes_to_hex(block_hash.binary))

            self._process_ready_new_blocks()
예제 #21
0
    def test_block_bodies_msg__get_block_transactions(self):
        txs = []
        txs_bytes = []
        txs_hashes = []

        tx_count = 10

        for i in range(1, tx_count):
            tx = mock_eth_messages.get_dummy_transaction(1)
            txs.append(tx)

            tx_bytes = rlp.encode(LegacyTransaction.serialize(tx))
            txs_bytes.append(tx_bytes)

            tx_hash = tx.hash()
            txs_hashes.append(tx_hash)

        al_tx = mock_eth_messages.get_dummy_access_list_transaction(11)
        txs.append(al_tx)
        txs_bytes.append(Transaction.serialize(al_tx))
        txs_hashes.append(al_tx.hash())

        uncles = [
            mock_eth_messages.get_dummy_block_header(2),
            mock_eth_messages.get_dummy_block_header(3),
        ]

        block_body = TransientBlockBody(txs, uncles)
        block_body_bytes = rlp.encode(block_body)
        block_bodies_msg = BlockBodiesEthProtocolMessage.from_body_bytes(
            block_body_bytes)

        parsed_txs_bytes = block_bodies_msg.get_block_transaction_bytes(0)
        self.assertEqual(len(parsed_txs_bytes), len(txs_hashes))

        for index, parsed_tx_bytes in enumerate(parsed_txs_bytes):
            self.assertEqual(
                convert.bytes_to_hex(txs_bytes[index]),
                convert.bytes_to_hex(parsed_tx_bytes),
                f"failed at index {index}",
            )

        parsed_txs_hashes = block_bodies_msg.get_block_transaction_hashes(0)
        self.assertEqual(len(parsed_txs_hashes), len(txs_hashes))

        for index, parsed_tx_hash in enumerate(parsed_txs_hashes):
            self.assertEqual(parsed_tx_hash, txs_hashes[index])
예제 #22
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
예제 #23
0
 def test_segwit_tx_hash(self):
     seg_tx = "010000000001024668fcfeba861f7f1bf4d386f15cc6923bd8425e0214686671775359d17a51d50100000000ffffffffdc5530f864de2fac86246426094d7b8586a452d6bd8c209bb891646afb3548770000000000ffffffff0220040000000000001600147771a1cab96e36344b1693d3d9f29180ca900482f5c40100000000001976a91483121cc1ea476c25d91191ff735a5e90518c732788ac02473044022006db5e6aa36dafb5d89a8522675d304a228d39ede1450aaab04f84b1fb57db2902203efb537cca9738c599d95d5c0ddcec6ebd11c6001541a89a468246318e0bd6fe012102d6b8b2ba44eb621ac9537ed7e11553bb02060abca88a9e6faf7697df5ac6d30c02483045022100b04869e06930db5d4e8e4d453d9aed1097a8dae57eef0274ebdc99a106796335022037a6b744900b9b6392448c961e8d793367a0caf675b9ca80349c593e505d8e9d0121034ef9635ae7cd714b2cf8af7e72f23b8b07c7f75d75df95da8d682ae17459091b00000000"
     seg_tx_bytes = convert.hex_to_bytes(seg_tx)
     self.assertTrue(btc_common_utils.is_segwit(seg_tx_bytes))
     self.assertEqual(
         convert.bytes_to_hex(
             btc_common_utils.get_txid(seg_tx_bytes).binary),
         "d9a057f11a21cf8afd32278e23fd2290660f05a3ffb582466eb5a1a5ece4ce85")
예제 #24
0
 def test_non_segwit_tx_hash(self):
     non_seg_tx = "0100000002d8c8df6a6fdd2addaf589a83d860f18b44872d13ee6ec3526b2b470d42a96d4d000000008b483045022100b31557e47191936cb14e013fb421b1860b5e4fd5d2bc5ec1938f4ffb1651dc8902202661c2920771fd29dd91cd4100cefb971269836da4914d970d333861819265ba014104c54f8ea9507f31a05ae325616e3024bd9878cb0a5dff780444002d731577be4e2e69c663ff2da922902a4454841aa1754c1b6292ad7d317150308d8cce0ad7abffffffff2ab3fa4f68a512266134085d3260b94d3b6cfd351450cff021c045a69ba120b2000000008b4830450220230110bc99ef311f1f8bda9d0d968bfe5dfa4af171adbef9ef71678d658823bf022100f956d4fcfa0995a578d84e7e913f9bb1cf5b5be1440bcede07bce9cd5b38115d014104c6ec27cffce0823c3fecb162dbd576c88dd7cda0b7b32b0961188a392b488c94ca174d833ee6a9b71c0996620ae71e799fc7c77901db147fa7d97732e49c8226ffffffff02c0175302000000001976a914a3d89c53bb956f08917b44d113c6b2bcbe0c29b788acc01c3d09000000001976a91408338e1d5e26db3fce21b011795b1c3c8a5a5d0788ac00000000"
     non_seg_tx_bytes = convert.hex_to_bytes(non_seg_tx)
     self.assertFalse(btc_common_utils.is_segwit(non_seg_tx_bytes))
     self.assertEqual(
         convert.bytes_to_hex(
             btc_common_utils.get_txid(non_seg_tx_bytes).binary),
         "9021b49d445c719106c95d561b9c3fac7bcb3650db67684a9226cd7fa1e1c1a0")
예제 #25
0
def generate_random_private_key_hex_str():
    """
    Generate hex string of random ECC private key
    :return: ECC private key hex string
    """

    # seed can be any random bytes of any length
    random_seed = os.urandom(100)
    private_key_bytes = make_private_key(random_seed)
    return convert.bytes_to_hex(private_key_bytes)
예제 #26
0
    def test_send_receive_block_and_key_real_block_1(self):
        self.node1.opts.blockchain_ignore_block_interval_count = 99999

        send_block = btc_block(real_block=RealBtcBlocks.BLOCK1)
        block_hash = "000000000000d76febe49ae1033fa22afebe6ac46ea255640268d7ede1084e6f"
        self.assertEqual(block_hash, convert.bytes_to_hex(send_block.block_hash().binary))

        received_block = self.send_received_block_and_key(block=send_block)
        self.assertEqual(9772, len(received_block.rawbytes()))
        self.assertEqual(536870912, received_block.version())
        self.assertEqual("bbb1f6f3a9324ab86ad23642994eac6624a9c9ef454d2f6e3bf68e3b094e0343",
                         convert.bytes_to_hex(received_block.merkle_root().binary))
        self.assertEqual(38, len(received_block.txns()))

        block_hash_object = Sha256Hash(binary=convert.hex_to_bytes(block_hash))
        self.assertEqual(1, len(self.node1.blocks_seen.contents))
        self.assertIn(block_hash_object, self.node1.blocks_seen.contents)
        self.assertEqual(1, len(self.node2.blocks_seen.contents))
        self.assertIn(block_hash_object, self.node2.blocks_seen.contents)
예제 #27
0
    def test_send_receive_block_and_key_real_block_2(self):
        self.node1.opts.blockchain_ignore_block_interval_count = 99999

        received_block = self.send_received_block_and_key(
            block=btc_block(real_block=RealBtcBlocks.BLOCK_WITNESS_REJECT))
        self.assertEqual(9613, len(received_block.rawbytes()))
        self.assertEqual(536870912, received_block.version())
        self.assertEqual("66bbbabedebee6c045284299069c407cdaa493166e64fe92ae03f358e96c7164",
                         convert.bytes_to_hex(received_block.merkle_root().binary))
        self.assertEqual(47, len(received_block.txns()))
예제 #28
0
    async def test_blxr_tx_ethereum_berlin(self):
        self.gateway_node.message_converter = EthNormalMessageConverter()
        self.gateway_node.network_num = 5

        # legacy
        result = await self.request(
            BxJsonRpcRequest(
                "1", RpcRequestType.BLXR_TX, {
                    rpc_constants.TRANSACTION_PARAMS_KEY:
                    convert.bytes_to_hex(eth_fixtures.LEGACY_TRANSACTION),
                    rpc_constants.STATUS_TRACK_PARAMS_KEY:
                    "True"
                }))
        self.assertEqual("1", result.id)
        self.assertIsNone(result.error)
        self.assertEqual(eth_fixtures.LEGACY_TRANSACTION_HASH,
                         result.result["tx_hash"])

        self.assertEqual(1, len(self.gateway_node.broadcast_messages))
        self.assertEqual(
            Sha256Hash(
                convert.hex_to_bytes(eth_fixtures.LEGACY_TRANSACTION_HASH)),
            self.gateway_node.broadcast_messages[0][0].tx_hash())

        # access list
        result = await self.request(
            BxJsonRpcRequest(
                "1", RpcRequestType.BLXR_TX, {
                    rpc_constants.TRANSACTION_PARAMS_KEY:
                    convert.bytes_to_hex(eth_fixtures.ACL_TRANSACTION),
                    rpc_constants.STATUS_TRACK_PARAMS_KEY:
                    "True"
                }))
        self.assertEqual("1", result.id)
        self.assertIsNone(result.error)
        self.assertEqual(eth_fixtures.ACL_TRANSACTION_HASH,
                         result.result["tx_hash"])

        self.assertEqual(2, len(self.gateway_node.broadcast_messages))
        self.assertEqual(
            Sha256Hash(convert.hex_to_bytes(
                eth_fixtures.ACL_TRANSACTION_HASH)),
            self.gateway_node.broadcast_messages[1][0].tx_hash())
예제 #29
0
    def start_transaction_recovery(
            self,
            unknown_sids: Iterable[int],
            unknown_hashes: Iterable[Sha256Hash],
            block_hash: Sha256Hash,
            connection: Optional[AbstractRelayConnection] = None):
        all_unknown_sids = []
        all_unknown_sids.extend(unknown_sids)
        tx_service = self._node.get_tx_service()

        # retrieving sids of txs with unknown contents
        for tx_hash in unknown_hashes:
            tx_sid = tx_service.get_short_id(tx_hash)
            all_unknown_sids.append(tx_sid)

        get_txs_message = GetTxsMessage(short_ids=all_unknown_sids)
        self._node.broadcast(
            get_txs_message,
            connection_types=[ConnectionType.RELAY_TRANSACTION])

        if connection is not None:
            tx_stats.add_txs_by_short_ids_event(
                all_unknown_sids,
                TransactionStatEventType.
                TX_UNKNOWN_SHORT_IDS_REQUESTED_BY_GATEWAY_FROM_RELAY,
                network_num=self._node.network_num,
                peer=connection.peer_desc,
                block_hash=convert.bytes_to_hex(block_hash.binary))
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.BLOCK_RECOVERY_STARTED,
                network_num=connection.network_num,
                request_hash=convert.bytes_to_hex(
                    crypto.double_sha256(get_txs_message.rawbytes())))
        else:
            block_stats.add_block_event_by_block_hash(
                block_hash,
                BlockStatEventType.BLOCK_RECOVERY_REPEATED,
                network_num=self._node.network_num,
                request_hash=convert.bytes_to_hex(
                    crypto.double_sha256(get_txs_message.rawbytes())))
예제 #30
0
 def msg_get_block_bodies(self,
                          msg: GetBlockBodiesEthProtocolMessage) -> None:
     block_hashes = msg.get_block_hashes()
     logger.debug(
         "Received unexpected get block bodies message from remote "
         "blockchain node for {} blocks: {}. Replying with empty block bodies.",
         len(block_hashes), ", ".join([
             convert.bytes_to_hex(block_hash.binary)
             for block_hash in block_hashes[:10]
         ]))
     empty_block_bodies_msg = BlockBodiesEthProtocolMessage(None, [])
     self.connection.enqueue_msg(empty_block_bodies_msg)