import hashlib from binascii import hexlify, unhexlify import time import struct import hmac from .constants import * from .opcodes import * from .hash import * from .encode import * # Bitcoin keys/ addresses # def create_priv(hex=False): """ :return: 32 bytes private key """ q = time.time() rnd = random.SystemRandom() a = rnd.randint(0,MAX_INT_PRIVATE_KEY) i = int((time.time()%0.01)*100000) h = a.to_bytes(32,byteorder="big") while True: h = hashlib.sha256(h).digest() if i>1: i -= 1 else: if int.from_bytes(h,byteorder="big") 73): return False # A signature is of type 0x30 (compound). if sig[0] != 0x30: return False # Make sure the length covers the entire signature. if sig[1] != (length - 3): return False # Extract the length of the R element. lenR = sig[3] # Make sure the length of the S element is still inside the signature. if (5 + lenR) >= length: return False # Extract the length of the S element. lenS = sig[5 + lenR] # Verify that the length of the signature matches the sum of the length # of the elements. if (lenR + lenS + 7) != length: return False # Check whether the R element is an integer. if sig[2] != 0x02: return False # Zero-length integers are not allowed for R. if lenR == 0: return False # Negative numbers are not allowed for R. if sig[4] & 0x80: return False # Null bytes at the start of R are not allowed, unless R would # otherwise be interpreted as a negative number. if (lenR > 1) and (sig[4] == 0x00) and (not sig[5] & 0x80): return False # Check whether the S element is an integer. if sig[lenR + 4] != 0x02: return False # Zero-length integers are not allowed for S. if lenS == 0: return False # Negative numbers are not allowed for S. if sig[lenR + 6] & 0x80: return False # Null bytes at the start of S are not allowed, unless S would otherwise be # interpreted as a negative number. if (lenS > 1) and (sig[lenR + 6] == 0x00) and (not sig[lenR + 7] & 0x80): return False return True # # Transaction encoding # def bits2target(bits): if type(bits) == str: bits = unhexlify(bits) if type(bits) == bytes: return int.from_bytes(bits[1:], 'big') * (2 ** (8 * (bits[0] - 3))) else: shift = bits >> 24 target = (bits & 0xffffff) * (1 << (8 * (shift - 3))) return target def target2difficulty(target): return 0x00000000FFFF0000000000000000000000000000000000000000000000000000 / target def bits2difficulty(bits): return target2difficulty(bits2target(bits)) def difficulty2target(difficulty): return int(0x00000000FFFF0000000000000000000000000000000000000000000000000000 / difficulty) def rh2s(tthash): return hexlify(tthash[::-1]).decode() def s2rh(hash_string): return unhexlify(hash_string)[::-1] def s2rh_step4(hash_string): h = unhexlify(hash_string) return reverse_hash(h) def reverse_hash(h): return struct.pack('>IIIIIIII', *struct.unpack('>IIIIIIII', h)[::-1])[::-1] def merkleroot(tx_hash_list): tx_hash_list = list(tx_hash_list) if len(tx_hash_list) == 1: return tx_hash_list[0] while True: new_hash_list = list() while tx_hash_list: h1 = tx_hash_list.pop(0) try: h2 = tx_hash_list.pop(0) except: h2 = h1 new_hash_list.append(double_sha256(h1 + h2)) if len(new_hash_list) > 1: tx_hash_list = new_hash_list else: return new_hash_list[0] def merkle_branches(tx_hash_list): tx_hash_list = list(tx_hash_list) branches = [] if len(tx_hash_list) == 1: return [] tx_hash_list.pop(0) while True: branches.append(tx_hash_list.pop(0)) new_hash_list = list() while tx_hash_list: h1 = tx_hash_list.pop(0) try: h2 = tx_hash_list.pop(0) except: h2 = h1 new_hash_list.append(double_sha256(h1 + h2)) if len(new_hash_list) > 1: tx_hash_list = new_hash_list else: if new_hash_list: branches.append(new_hash_list.pop(0)) return branches def merkleroot_from_branches(merkle_branches, coinbase_hash_bin): merkle_root = coinbase_hash_bin for h in merkle_branches: if type(h) == str: h = unhexlify(h) merkle_root = double_sha256(merkle_root + h) return merkle_root # # # def var_int(data): e, s = 1, 0 if data[:1] == b'\xfd': s, e = 1, 3 elif data[:1] == b'\xfe': s = 1 e = 5 elif data[:1] == b'\xff': s = 1 e = 9 i = int.from_bytes(data[s:e], byteorder='little', signed=False) return (i, e) def from_var_int(data): # retrun e = 1 s = 0 if data[:1] == b'\xfd': s = 1 e = 3 elif data[:1] == b'\xfe': s = 1 e = 5 elif data[:1] == b'\xff': s = 1 e = 9 i = int.from_bytes(data[s:e], byteorder='little', signed=False) return i def var_int_len(byte): e = 1 if byte == 253: e = 3 elif byte == 254: e = 5 elif byte == 255: e = 9 return e def to_var_int(i): if i < 253: return i.to_bytes(1, byteorder='little') if i <= 0xffff: return b'\xfd' + i.to_bytes(2, byteorder='little') if i <= 0xffffffff: return b'\xfe' + i.to_bytes(4, byteorder='little') return b'\xff' + i.to_bytes(8, byteorder='little') def read_var_int(stream): l = stream.read(1) bytes_length = var_int_len(l[0]) return l + stream.read(bytes_length - 1) def read_var_list(stream, data_type): count = from_var_int(read_var_int(stream)) return [data_type.deserialize(stream) for i in range(count)] # generic big endian MPI format def bn_bytes(v, have_ext=False): ext = 0 if have_ext: ext = 1 return ((v.bit_length() + 7) // 8) + ext def bn2bin(v): s = bytearray() i = bn_bytes(v) while i > 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)