def test_unpackers(): b = bytes(range(256)) assert util.unpack_le_int32_from(b, 0) == (50462976, ) assert util.unpack_le_int32_from(b, 42) == (757869354, ) assert util.unpack_le_int64_from(b, 0) == (506097522914230528, ) assert util.unpack_le_int64_from(b, 42) == (3544384782113450794, ) assert util.unpack_le_uint16_from(b, 0) == (256, ) assert util.unpack_le_uint16_from(b, 42) == (11050, ) assert util.unpack_le_uint32_from(b, 0) == (50462976, ) assert util.unpack_le_uint32_from(b, 42) == (757869354, ) assert util.unpack_le_uint64_from(b, 0) == (506097522914230528, ) assert util.unpack_le_uint64_from(b, 42) == (3544384782113450794, )
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') from None return ops
def get_ops(cls, script): ''' Returns a tuple list of (op_code, index of next op in script, pushed bytes if any) If at any point the script fails do decode, a tuple of (-1, len(script), remaining script) is appended ''' ops = [] # The unpacks or script[n] n = 0 try: while n < len(script): op = script[n] op_v = (script[n], n + 1) n += 1 if op <= OpCodes.OP_PUSHDATA4: # Raw bytes follow if op < OpCodes.OP_PUSHDATA1: dlen = op n1 = 0 elif op == OpCodes.OP_PUSHDATA1: dlen = script[n] n1 = 1 elif op == OpCodes.OP_PUSHDATA2: dlen, = unpack_le_uint16_from(script[n:n + 2]) n1 = 2 else: dlen, = unpack_le_uint32_from(script[n:n + 4]) n1 = 4 if n + n1 + dlen > len(script): raise IndexError n += n1 op_v = (op, n + dlen, script[n:n + dlen]) n += dlen ops.append(op_v) except (IndexError, struct.error): # n - 1 because we read a byte first ops.append((-1, len(script), script[n - 1:])) 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
def read_le_uint16(buf, cursor): result, = unpack_le_uint16_from(buf, cursor) return result, cursor + 2