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
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 )
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)
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
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
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
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))
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>"
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))
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")
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()), )
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)
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)
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]
def __init__( self, hash: Sha256Hash, block: memoryview ) -> None: self.hash = str(hash) self.block = convert.bytes_to_hex(block)
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
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()
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])
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 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")
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")
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)
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)
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()))
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())
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())))
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)