electrum-personal-server

Maximally lightweight electrum server for a single user
git clone https://git.parazyd.org/electrum-personal-server
Log | Files | Refs | README

hashes.py (2865B)


      1 
      2 import hashlib
      3 import binascii
      4 import math
      5 
      6 ## stuff copied from electrum's source
      7 
      8 def to_bytes(something, encoding='utf8'):
      9     """
     10     cast string to bytes() like object, but for python2 support
     11     it's bytearray copy
     12     """
     13     if isinstance(something, bytes):
     14         return something
     15     if isinstance(something, str):
     16         return something.encode(encoding)
     17     elif isinstance(something, bytearray):
     18         return bytes(something)
     19     else:
     20         raise TypeError("Not a string or bytes like object")
     21 
     22 def sha256(x):
     23     x = to_bytes(x, 'utf8')
     24     return bytes(hashlib.sha256(x).digest())
     25 
     26 def bh2u(x):
     27     return binascii.hexlify(x).decode('ascii')
     28 
     29 def script_to_scripthash(script):
     30     """Electrum uses a format hash(scriptPubKey) as the index keys"""
     31     h = sha256(bytes.fromhex(script))[0:32]
     32     return bh2u(bytes(reversed(h)))
     33 
     34 #the 'result' field in the blockchain.scripthash.subscribe method
     35 # reply uses this as a summary of the address
     36 def get_status_electrum(h):
     37     if not h:
     38         return None
     39     if len(h) == 0:
     40         return None
     41     status = ''
     42     for tx_hash, height in h:
     43         status += tx_hash + ':%d:' % height
     44     return bh2u(hashlib.sha256(status.encode('ascii')).digest())
     45 
     46 bfh = bytes.fromhex
     47 hash_encode = lambda x: bh2u(x[::-1])
     48 hash_decode = lambda x: bfh(x)[::-1]
     49 
     50 def Hash(x):
     51     x = to_bytes(x, 'utf8')
     52     out = bytes(sha256(sha256(x)))
     53     return out
     54 
     55 def hash_merkle_root(merkle_s, target_hash, pos):
     56     h = hash_decode(target_hash)
     57     for i in range(len(merkle_s)):
     58         item = merkle_s[i]
     59         h = Hash(hash_decode(item) + h) if ((pos >> i) & 1) else Hash(
     60             h + hash_decode(item))
     61     return hash_encode(h)
     62 
     63 def hash_160(public_key):
     64     try:
     65         md = hashlib.new('ripemd160')
     66         md.update(sha256(public_key))
     67         return md.digest()
     68     except BaseException:
     69         from . import ripemd
     70         md = ripemd.new(sha256(public_key))
     71         return md.digest()
     72 
     73 ## end of electrum copypaste
     74 
     75 def script_to_address(scriptPubKey, rpc):
     76     return rpc.call("decodescript", [scriptPubKey])["addresses"][0]
     77 
     78 def address_to_script(addr, rpc):
     79     return rpc.call("validateaddress", [addr])["scriptPubKey"]
     80 
     81 def address_to_scripthash(addr, rpc):
     82     return script_to_scripthash(address_to_script(addr, rpc))
     83 
     84 # doesnt really fit here but i dont want to clutter up server.py
     85 
     86 unit_list = list(zip(['B', 'kB', 'MB', 'GB', 'TB', 'PB'], [0, 0, 1, 2, 2, 2]))
     87 
     88 def bytes_fmt(num):
     89     """Human friendly file size"""
     90     if num > 1:
     91         exponent = min(int(math.log(num, 1000)), len(unit_list) - 1)
     92         quotient = float(num) / 1000**exponent
     93         unit, num_decimals = unit_list[exponent]
     94         format_string = '{:.%sf} {}' % (num_decimals)
     95         return format_string.format(quotient, unit)
     96     if num == 0:
     97         return '0 bytes'
     98     if num == 1:
     99         return '1 byte'
    100