def parse_segwit(s): tx = { "version": 1, "mark": None, "flag": None, "txi.count": 0, "txis": [], "txo.count": 0, "txos": [], # "wits": append to each txi "locktime": 0, "hash_all": None } tx["version"] = util.little_endian_to_int(s.read(4)) tx["mark"] = s.read(1) tx["flag"] = s.read(1) if tx["mark"] != b"\x00" and tx["flag"] != b"\x01": raise RuntimeError('not a segwit transaction {}'.format(tx["flag"])) tx["txi.count"] = util.read_varint(s) for _ in range(tx["txi.count"]): tx["txis"].append(parse_txi(s)) tx["txo.count"] = util.read_varint(s) for _ in range(tx["txo.count"]): tx["txos"].append(parse_txo(s)) # parse witness script for txi in tx["txis"]: count = util.read_varint(s) for _ in range(count): length = util.read_varint(s) if length == 0: # ? txi["wits"].append(0) else: txi["wits"].append(s.read(length)) tx["locktime"] = util.little_endian_to_int(s.read(4)) # locktime is an integer in 4 bytes, little-endian return tx
def _read_msg(self): msg_type = read_varint(self.istream) if msg_type == MSG_TICK or msg_type == MSG_STRINGS: raise Exception('_read_msg called for INTERNAL msg_type:{}'.format(msg_type)) msg_size = read_varint(self.istream) if msg_size <= MAX_MSG_SIZE: msg = self.msg_cls() msg.ParseFromString(self.istream.read(msg_size)) return Msg(msg, self.lookup_string)
def parse_headers(s): # number of headers is in a varint num_headers = util.read_varint(s) # initialize the blocks array blocks = [] # loop through number of headers times for _ in range(num_headers): # add a block to the blocks array by parsing the stream blocks.append(block.parse(s)) # read the next varint (num_txs) num_txs = util.read_varint(s) # num_txs should be 0 or raise a RuntimeError if num_txs != 0: raise RuntimeError('number of txs not 0') return {'blocks': blocks}
def _has_next(self): try: while True: pos = self.istream.tell() msg_type = read_varint(self.istream) if msg_type == MSG_TICK: self.tick = read_varint(self.istream) elif msg_type == MSG_STRINGS: return False # at end of file elif msg_type == self.msg_id: self.istream.seek(pos) return True else: raise MalformedAspect('Invalid msg_type:{}, expected [{},{},{}]'.format(msg_type, self.msg_id, MSG_TICK, MSG_STRINGS)) except Exception as e: log.warning('Exception: {}'.format(e)) return False
def parse_legacy(s): tx = { "version": 1, # "mark": None, # "flag": None, "txi.count": 0, "txis": [], "txo.count": 0, "txos": [], # "wits": None, "locktime": 0 } tx["version"] = util.little_endian_to_int(s.read(4)) tx["txi.count"] = util.read_varint(s) for _ in range(tx["txi.count"]): tx["txis"].append(parse_txi(s)) tx["txo.count"] = util.read_varint(s) for _ in range(tx["txo.count"]): tx["txos"].append(parse_txo(s)) tx["locktime"] = util.little_endian_to_int(s.read(4)) # locktime is an integer in 4 bytes, little-endian return tx
def parse_merkleblock(s): """Takes a byte stream and parses a merkle block. Returns a Merkle Block object""" # version - 4 bytes, Little-Endian integer version = util.little_endian_to_int(s.read(4)) # prev_block - 32 bytes, Little-Endian (use [::-1]) prev_block_hash = s.read(32)[::-1] # merkle_root - 32 bytes, Little-Endian (use [::-1]) merkle_root = s.read(32)[::-1] # timestamp - 4 bytes, Little-Endian integer timestamp = util.little_endian_to_int(s.read(4)) # bits - 4 bytes bits = s.read(4) # nonce - 4 bytes nonce = s.read(4) # total transactions in block - 4 bytes, Little-Endian integer total = util.little_endian_to_int(s.read(4)) # number of transaction hashes - varint num_hashes = util.read_varint(s) # each transaction is 32 bytes, Little-Endian hashes = [] for _ in range(num_hashes): hashes.append(s.read(32)[::-1]) # length of flags field - varint flags_length = util.read_varint(s) # read the flags field flags = s.read(flags_length) return { 'version': version, 'prev_block_hash': prev_block_hash, 'merkle_root': merkle_root, 'timestamp': timestamp, 'bits': bits, 'nonce': nonce, 'total': total, 'hashes': hashes, 'flags': flags }
def __init__(self, aspect_path, raw_reader): try: self.msg_cls = mapper.aspect_map[aspect_path]['cls'] self.msg_id = mapper.aspect_map[aspect_path]['id'] except KeyError as e: raise err.UnknownAspectPath(aspect_path) self.raw = raw_reader self.aspect_path = aspect_path self.string_table = self.raw.read_string_table() self.tick = 0 self.istream = self.raw.get_stream() try: self.replay_id = read_varint(self.istream) except Exception as e: raise err.MalformedAspect(e)
def parse(s): length = util.read_varint(s) commands = [] # initialize the commands array count = 0 # initialize the number of bytes we've read to 0 while count < length: # loop until we've read length bytes temp = s.read(1)[0] # get code count += 1 # increment the bytes we've read if 1 <= temp <= 75: # if the current byte is between 1 and 75 inclusive commands.append(s.read(temp)) # add the next n bytes as an cmd count += temp # increase the count by n elif temp == 76: # op_pushdata1 data_length = util.little_endian_to_int(s.read(1)) commands.append(s.read(data_length)) count += data_length + 1 elif temp == 77: # op_pushdata2 data_length = util.little_endian_to_int(s.read(2)) commands.append(s.read(data_length)) count += data_length + 2 else: # we have an op_code. set the current byte to op_code commands.append(temp) # add the op_code to the list of commands if count != length: raise SyntaxError('parsing script failed') return length, commands