tecc_fast.py - electrum - Electrum Bitcoin wallet
HTML git clone https://git.parazyd.org/electrum
DIR Log
DIR Files
DIR Refs
DIR Submodules
---
tecc_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.")