funga-eth

Ethereum implementation of the funga keystore and signer
Info | Log | Files | Refs | README | LICENSE

encoding.py (2691B)


      1 # standard imports
      2 import logging
      3 
      4 # external imports
      5 import coincurve
      6 import sha3
      7 from hexathon import (
      8         strip_0x,
      9         uniform,
     10         )
     11 
     12 logg = logging.getLogger(__name__)
     13 
     14 
     15 def private_key_from_bytes(b):
     16     return coincurve.PrivateKey(secret=b)
     17 
     18 
     19 def public_key_bytes_to_address(pubk_bytes, result_format='hex'):
     20     h = sha3.keccak_256()
     21     logg.debug('public key bytes {}'.format(pubk_bytes.hex()))
     22     h.update(pubk_bytes[1:])
     23     z = h.digest()[12:]
     24     if result_format == 'hex':
     25         return to_checksum_address(z[:20].hex())
     26     elif result_format == 'bytes':
     27         return z[:20]
     28     raise ValueError('invalid result format "{}"'.format(result_format))
     29 
     30 
     31 def public_key_to_address(pubk, result_format='hex'):
     32     pubk_bytes = pubk.format(compressed=False)
     33     return public_key_bytes_to_address(pubk_bytes, result_format='hex')
     34 
     35 
     36 def private_key_to_address(pk, result_format='hex'):
     37     pubk = coincurve.PublicKey.from_secret(pk.secret)
     38     #logg.debug('secret {} '.format(pk.secret.hex()))
     39     return public_key_to_address(pubk, result_format)
     40 
     41 
     42 def private_key_to_public_key(pk, result_format='hex'):
     43     pubk = coincurve.PublicKey.from_secret(pk.secret)
     44     r = pubk.format(compressed=False)
     45     if result_format=='hex':
     46         r = r.hex()
     47     return r
     48 
     49 
     50 def is_address(address_hex):
     51     try:
     52         address_hex = strip_0x(address_hex, pad=False)
     53     except ValueError:
     54         return False
     55     return len(address_hex) == 40
     56 
     57 
     58 def is_checksum_address(address_hex):
     59     hx = None
     60     try:
     61         hx = to_checksum(address_hex)
     62     except ValueError:
     63         return False
     64     return hx == strip_0x(address_hex)
     65 
     66 
     67 def to_checksum_address(address_hex):
     68         address_hex = strip_0x(address_hex, pad=False)
     69         if len(address_hex) != 40:
     70             raise ValueError('Invalid address length')
     71         address_hex = uniform(address_hex)
     72         h = sha3.keccak_256()
     73         h.update(address_hex.encode('utf-8'))
     74         z = h.digest()
     75 
     76         #checksum_address_hex = '0x'
     77         checksum_address_hex = ''
     78 
     79         for (i, c) in enumerate(address_hex):
     80             if c in '1234567890':
     81                 checksum_address_hex += c
     82             elif c in 'abcdef':
     83                 if z[int(i / 2)] & (0x80 >> ((i % 2) * 4)) > 1:
     84                     checksum_address_hex += c.upper()
     85                 else:
     86                     checksum_address_hex += c
     87 
     88         return checksum_address_hex
     89 
     90 to_checksum = to_checksum_address
     91 
     92 ethereum_recid_modifier = 35
     93 
     94 def chain_id_to_v(chain_id, signature):
     95     v = signature[64]
     96     return (chain_id * 2) + ethereum_recid_modifier + v
     97 
     98 def chainv_to_v(chain_id, v):
     99     return v - ethereum_recid_modifier - (chain_id * 2)