def assert_claim_id(self, value): '''Raise an RPCError if the value is not a valid claim id hash.''' try: if len(util.hex_to_bytes(value)) == 20: return except Exception: pass raise RPCError(1, f'{value} should be a claim id hash')
def assert_tx_hash(self, value): '''Raise an RPCError if the value is not a valid transaction hash.''' try: if len(util.hex_to_bytes(value)) == 32: return except Exception: pass raise RPCError(1, f'{value} should be a transaction hash')
async def getrawtransactions(self, hex_hashes, replace_errs=True): """Return the serialized raw transactions with the given hashes. Replaces errors with None by default.""" params_iterable = ((hex_hash, 0) for hex_hash in hex_hashes) txs = await self._send_vector('getrawtransaction', params_iterable, replace_errs=replace_errs) # Convert hex strings to bytes return [hex_to_bytes(tx) if tx else None for tx in txs]
async def utxo_get_address(self, tx_hash, index): # fixme: lbryum # Used only for electrum client command-line requests. We no # longer index by address, so need to request the raw # transaction. So it works for any TXO not just UTXOs. self.assert_tx_hash(tx_hash) try: index = int(index) if index < 0: raise ValueError except ValueError: raise RPCError(1, "index has to be >= 0 and integer") raw_tx = await self.daemon_request('getrawtransaction', tx_hash) if not raw_tx: return None raw_tx = util.hex_to_bytes(raw_tx) tx = self.coin.DESERIALIZER(raw_tx).read_tx() if index >= len(tx.outputs): return None return self.coin.address_from_script(tx.outputs[index].pk_script)
async def raw_blocks(self, hex_hashes): '''Return the raw binary blocks with the given hex hashes.''' params_iterable = ((h, False) for h in hex_hashes) blocks = await self._send_vector('getblock', params_iterable) raw_blocks = [] valid_tx_tree = {} for block in blocks: # Convert to bytes from hex raw_block = hex_to_bytes(block) raw_blocks.append(raw_block) # Check if previous block is valid prev = self.prev_hex_hash(raw_block) votebits = unpack_le_uint16_from(raw_block[100:102])[0] valid_tx_tree[prev] = self.is_valid_tx_tree(votebits) processed_raw_blocks = [] for hash, raw_block in zip(hex_hashes, raw_blocks): if hash in valid_tx_tree: is_valid = valid_tx_tree[hash] else: # Do something complicated to figure out if this block is valid header = await self._send_single('getblockheader', (hash, )) if 'nextblockhash' not in header: raise DaemonError(f'Could not find next block for {hash}') next_hash = header['nextblockhash'] next_header = await self._send_single('getblockheader', (next_hash, )) is_valid = self.is_valid_tx_tree(next_header['votebits']) if is_valid: processed_raw_blocks.append(raw_block) else: # If this block is invalid remove the normal transactions self.logger.info(f'block {hash} is invalidated') processed_raw_blocks.append(self.strip_tx_tree(raw_block)) return processed_raw_blocks
def hex_str_to_hash(x): '''Convert a displayed hex string to a binary hash.''' return bytes(reversed(hex_to_bytes(x)))
async def raw_blocks(self, hex_hashes): '''Return the raw binary blocks with the given hex hashes.''' params_iterable = ((h, False) for h in hex_hashes) blocks = await self._send_vector('getblock', params_iterable) # Convert hex string to bytes return [hex_to_bytes(block) for block in blocks]