electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

ecc_fast.py (5934B)


      1 # taken (with minor modifications) from pycoin
      2 # https://github.com/richardkiss/pycoin/blob/01b1787ed902df23f99a55deb00d8cd076a906fe/pycoin/ecdsa/native/secp256k1.py
      3 
      4 import os
      5 import sys
      6 import traceback
      7 import ctypes
      8 from ctypes import (
      9     byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer,
     10     CFUNCTYPE, POINTER, cast
     11 )
     12 
     13 from .logging import get_logger
     14 
     15 
     16 _logger = get_logger(__name__)
     17 
     18 
     19 SECP256K1_FLAGS_TYPE_MASK = ((1 << 8) - 1)
     20 SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0)
     21 SECP256K1_FLAGS_TYPE_COMPRESSION = (1 << 1)
     22 # /** The higher bits contain the actual data. Do not use directly. */
     23 SECP256K1_FLAGS_BIT_CONTEXT_VERIFY = (1 << 8)
     24 SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9)
     25 SECP256K1_FLAGS_BIT_COMPRESSION = (1 << 8)
     26 
     27 # /** Flags to pass to secp256k1_context_create. */
     28 SECP256K1_CONTEXT_VERIFY = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
     29 SECP256K1_CONTEXT_SIGN = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
     30 SECP256K1_CONTEXT_NONE = (SECP256K1_FLAGS_TYPE_CONTEXT)
     31 
     32 SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
     33 SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION)
     34 
     35 
     36 class LibModuleMissing(Exception): pass
     37 
     38 
     39 def load_library():
     40     if sys.platform == 'darwin':
     41         library_paths = (os.path.join(os.path.dirname(__file__), 'libsecp256k1.0.dylib'),
     42                          'libsecp256k1.0.dylib')
     43     elif sys.platform in ('windows', 'win32'):
     44         library_paths = (os.path.join(os.path.dirname(__file__), 'libsecp256k1-0.dll'),
     45                          'libsecp256k1-0.dll')
     46     elif 'ANDROID_DATA' in os.environ:
     47         library_paths = ('libsecp256k1.so',)
     48     else:  # desktop Linux and similar
     49         library_paths = (os.path.join(os.path.dirname(__file__), 'libsecp256k1.so.0'),
     50                          'libsecp256k1.so.0')
     51 
     52     exceptions = []
     53     secp256k1 = None
     54     for libpath in library_paths:
     55         try:
     56             secp256k1 = ctypes.cdll.LoadLibrary(libpath)
     57         except BaseException as e:
     58             exceptions.append(e)
     59         else:
     60             break
     61     if not secp256k1:
     62         _logger.error(f'libsecp256k1 library failed to load. exceptions: {repr(exceptions)}')
     63         return None
     64 
     65     try:
     66         secp256k1.secp256k1_context_create.argtypes = [c_uint]
     67         secp256k1.secp256k1_context_create.restype = c_void_p
     68 
     69         secp256k1.secp256k1_context_randomize.argtypes = [c_void_p, c_char_p]
     70         secp256k1.secp256k1_context_randomize.restype = c_int
     71 
     72         secp256k1.secp256k1_ec_pubkey_create.argtypes = [c_void_p, c_void_p, c_char_p]
     73         secp256k1.secp256k1_ec_pubkey_create.restype = c_int
     74 
     75         secp256k1.secp256k1_ecdsa_sign.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p, c_void_p, c_void_p]
     76         secp256k1.secp256k1_ecdsa_sign.restype = c_int
     77 
     78         secp256k1.secp256k1_ecdsa_verify.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p]
     79         secp256k1.secp256k1_ecdsa_verify.restype = c_int
     80 
     81         secp256k1.secp256k1_ec_pubkey_parse.argtypes = [c_void_p, c_char_p, c_char_p, c_size_t]
     82         secp256k1.secp256k1_ec_pubkey_parse.restype = c_int
     83 
     84         secp256k1.secp256k1_ec_pubkey_serialize.argtypes = [c_void_p, c_char_p, c_void_p, c_char_p, c_uint]
     85         secp256k1.secp256k1_ec_pubkey_serialize.restype = c_int
     86 
     87         secp256k1.secp256k1_ecdsa_signature_parse_compact.argtypes = [c_void_p, c_char_p, c_char_p]
     88         secp256k1.secp256k1_ecdsa_signature_parse_compact.restype = c_int
     89 
     90         secp256k1.secp256k1_ecdsa_signature_normalize.argtypes = [c_void_p, c_char_p, c_char_p]
     91         secp256k1.secp256k1_ecdsa_signature_normalize.restype = c_int
     92 
     93         secp256k1.secp256k1_ecdsa_signature_serialize_compact.argtypes = [c_void_p, c_char_p, c_char_p]
     94         secp256k1.secp256k1_ecdsa_signature_serialize_compact.restype = c_int
     95 
     96         secp256k1.secp256k1_ecdsa_signature_parse_der.argtypes = [c_void_p, c_char_p, c_char_p, c_size_t]
     97         secp256k1.secp256k1_ecdsa_signature_parse_der.restype = c_int
     98 
     99         secp256k1.secp256k1_ecdsa_signature_serialize_der.argtypes = [c_void_p, c_char_p, c_void_p, c_char_p]
    100         secp256k1.secp256k1_ecdsa_signature_serialize_der.restype = c_int
    101 
    102         secp256k1.secp256k1_ec_pubkey_tweak_mul.argtypes = [c_void_p, c_char_p, c_char_p]
    103         secp256k1.secp256k1_ec_pubkey_tweak_mul.restype = c_int
    104 
    105         secp256k1.secp256k1_ec_pubkey_combine.argtypes = [c_void_p, c_char_p, c_void_p, c_size_t]
    106         secp256k1.secp256k1_ec_pubkey_combine.restype = c_int
    107 
    108         # --enable-module-recovery
    109         try:
    110             secp256k1.secp256k1_ecdsa_recover.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p]
    111             secp256k1.secp256k1_ecdsa_recover.restype = c_int
    112 
    113             secp256k1.secp256k1_ecdsa_recoverable_signature_parse_compact.argtypes = [c_void_p, c_char_p, c_char_p, c_int]
    114             secp256k1.secp256k1_ecdsa_recoverable_signature_parse_compact.restype = c_int
    115         except (OSError, AttributeError):
    116             raise LibModuleMissing('libsecp256k1 library found but it was built '
    117                                    'without required module (--enable-module-recovery)')
    118 
    119         secp256k1.ctx = secp256k1.secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)
    120         ret = secp256k1.secp256k1_context_randomize(secp256k1.ctx, os.urandom(32))
    121         if not ret:
    122             _logger.error('secp256k1_context_randomize failed')
    123             return None
    124 
    125         return secp256k1
    126     except (OSError, AttributeError) as e:
    127         _logger.error(f'libsecp256k1 library was found and loaded but there was an error when using it: {repr(e)}')
    128         return None
    129 
    130 
    131 _libsecp256k1 = None
    132 try:
    133     _libsecp256k1 = load_library()
    134 except BaseException as e:
    135     _logger.error(f'failed to load libsecp256k1: {repr(e)}')
    136 
    137 
    138 if _libsecp256k1 is None:
    139     # hard fail:
    140     sys.exit(f"Error: Failed to load libsecp256k1.")