import math import io import struct def rh2s(raw_hash): """ Encode raw transaction hash to HEX string with bytes order change :param raw_hash: transaction hash in bytes string. :return: HEX encoded string. """ return raw_hash[::-1].hex() def s2rh(hash_string): """ Decode HEX transaction hash to bytes with byte order change :param raw_hash: transaction hash in bytes string. :return: bytes string. """ return bytes.fromhex(hash_string)[::-1] def s2rh_step4(hash_string): h = bytes.fromhex(hash_string) return reverse_hash(h) def reverse_hash(raw_hash): """ Reverse hash order :param raw_hash: bytes string. :return: bytes string. """ return struct.pack('>IIIIIIII', *struct.unpack('>IIIIIIII', raw_hash)[::-1])[::-1] def bytes_needed(n): """ Calculate bytes needed to convert integer to bytes. :param n: integer. :return: integer. """ if n == 0: return 1 return math.ceil(n.bit_length()/8) def int_to_bytes(i, byteorder='big'): """ Convert integer to bytes. :param n: integer. :param byteorder: (optional) byte order 'big' or 'little', by default 'big'. :return: bytes. """ return i.to_bytes(bytes_needed(i), byteorder=byteorder, signed=False) def bytes_to_int(i, byteorder='big'): """ Convert bytes to integer. :param i: bytes. :param byteorder: (optional) byte order 'big' or 'little', by default 'big'. :return: integer. """ return int.from_bytes(i, byteorder=byteorder, signed=False) # variable integer def int_to_var_int(i): """ Convert integer to variable integer :param i: integer. :return: bytes. """ if i < 0xfd: return struct.pack(' 0: s.append((v >> ((i - 1) * 8)) & 0xff) i -= 1 return s def bin2bn(s): l = 0 for ch in s: l = (l << 8) | ch return l def bn2mpi(v): have_ext = False if v.bit_length() > 0: have_ext = (v.bit_length() & 0x07) == 0 neg = False if v < 0: neg = True v = -v s = struct.pack(b">I", bn_bytes(v, have_ext)) ext = bytearray() if have_ext: ext.append(0) v_bin = bn2bin(v) if neg: if have_ext: ext[0] |= 0x80 else: v_bin[0] |= 0x80 return s + ext + v_bin def mpi2bn(s): if len(s) < 4: return None s_size = bytes(s[:4]) v_len = struct.unpack(b">I", s_size)[0] if len(s) != (v_len + 4): return None if v_len == 0: return 0 v_str = bytearray(s[4:]) neg = False i = v_str[0] if i & 0x80: neg = True i &= ~0x80 v_str[0] = i v = bin2bn(v_str) if neg: return -v return v # bitcoin-specific little endian format, with implicit size def mpi2vch(s): r = s[4:] # strip size # if r: r = r[::-1] # reverse string, converting BE->LE # else: r=b'\x00' return r def bn2vch(v): return bytes(mpi2vch(bn2mpi(v))) def vch2mpi(s): r = struct.pack(b">I", len(s)) # size r += s[::-1] # reverse string, converting LE->BE return r def vch2bn(s): return mpi2bn(vch2mpi(s)) def i2b(i): return bn2vch(i) def b2i(b): return vch2bn(b) def get_stream(stream): if type(stream) != io.BytesIO: if type(stream) == str: stream = bytes.fromhex(stream) if type(stream) == bytes: stream = io.BytesIO(stream) else: raise TypeError return stream