def get_ops(cls, script): ops = [] # The unpacks or script[n] below throw on truncated scripts try: n = 0 while n < len(script): op = script[n] n += 1 if op <= OpCodes.OP_PUSHDATA4: # Raw bytes follow if op < OpCodes.OP_PUSHDATA1: dlen = op elif op == OpCodes.OP_PUSHDATA1: dlen = script[n] n += 1 elif op == OpCodes.OP_PUSHDATA2: dlen, = unpack_le_uint16_from(script[n: n + 2]) n += 2 else: dlen, = unpack_le_uint32_from(script[n: n + 4]) n += 4 if n + dlen > len(script): raise IndexError op = (op, script[n:n + dlen]) n += dlen ops.append(op) except Exception: # Truncated script; e.g. tx_hash # ebc9fa1196a59e192352d76c0f6e73167046b9d37b8302b6bb6968dfd279b767 raise ScriptError('truncated script') return ops
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 _read_le_uint16(self): result, = unpack_le_uint16_from(self.binary, self.cursor) self.cursor += 2 return result