1
0
Files
electrum/electrum/ecc_fast.py
SomberNight e455677284 win build: bump pyinstaller (4.10->5.11)
In `build-electrum-git.sh`, the `-w` CLI arg is removed: it was apparently ignored as we are using a .spec file,
and pyinstaller 5.0+ is now raising a hard error (see https://github.com/pyinstaller/pyinstaller/issues/6660).
```
option(s) not allowed:
  --console/--nowindowed/--windowed/--noconsole
makespec options not valid when a .spec file is given
```

-----

In ecc_fast.py, we don't sys.exit() anymore as pyinstaller 5.0+ tries to import electrum during the Analysis phase.
see https://github.com/pyinstaller/pyinstaller/pull/6171

```
57912 INFO: Looking for dynamic libraries
1746 INFO: gettext setting initial language to None
1932 ERROR: libsecp256k1 library failed to load. exceptions: [FileNotFoundError("Could not find module 'C:\\python3\\lib\\site-packages\\electrum\\libsecp256k1-2.dll' (or one of its depende
ncies). Try using the full path with constructor syntax."), FileNotFoundError("Could not find module 'C:\\python3\\lib\\site-packages\\electrum\\libsecp256k1-1.dll' (or one of its dependenc
ies). Try using the full path with constructor syntax."), FileNotFoundError("Could not find module 'C:\\python3\\lib\\site-packages\\electrum\\libsecp256k1-0.dll' (or one of its dependencie
s). Try using the full path with constructor syntax."), FileNotFoundError("Could not find module 'libsecp256k1-2.dll' (or one of its dependencies). Try using the full path with constructor
syntax."), FileNotFoundError("Could not find module 'libsecp256k1-1.dll' (or one of its dependencies). Try using the full path with constructor syntax."), FileNotFoundError("Could not find
module 'libsecp256k1-0.dll' (or one of its dependencies). Try using the full path with constructor syntax.")]
Traceback (most recent call last):
  File "C:\python3\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\python3\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\python3\scripts\pyinstaller.exe\__main__.py", line 7, in <module>
  File "C:\python3\lib\site-packages\PyInstaller\__main__.py", line 194, in _console_script_run
    run()
  File "C:\python3\lib\site-packages\PyInstaller\__main__.py", line 180, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "C:\python3\lib\site-packages\PyInstaller\__main__.py", line 61, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "C:\python3\lib\site-packages\PyInstaller\building\build_main.py", line 1006, in main
    build(specfile, distpath, workpath, clean_build)
  File "C:\python3\lib\site-packages\PyInstaller\building\build_main.py", line 928, in build
    exec(code, spec_namespace)
  File "deterministic.spec", line 55, in <module>
    a = Analysis([home+'run_electrum',
  File "C:\python3\lib\site-packages\PyInstaller\building\build_main.py", line 428, in __init__
    self.__postinit__()
  File "C:\python3\lib\site-packages\PyInstaller\building\datastruct.py", line 184, in __postinit__
    self.assemble()
  File "C:\python3\lib\site-packages\PyInstaller\building\build_main.py", line 736, in assemble
    isolated.call(find_binary_dependencies, self.binaries, self.binding_redirects, collected_packages)
  File "C:\python3\lib\site-packages\PyInstaller\isolated\_parent.py", line 372, in call
    return isolated.call(function, *args, **kwargs)
  File "C:\python3\lib\site-packages\PyInstaller\isolated\_parent.py", line 302, in call
    raise RuntimeError(f"Child process call to {function.__name__}() failed with:\n" + output)
RuntimeError: Child process call to find_binary_dependencies() failed with:
  File "C:\python3\lib\site-packages\PyInstaller\isolated\_child.py", line 63, in run_next_command
    output = function(*args, **kwargs)
  File "C:\python3\lib\site-packages\PyInstaller\building\build_main.py", line 177, in find_binary_dependencies
    __import__(package)
  File "C:\python3\lib\site-packages\electrum\__init__.py", line 20, in <module>
    from .wallet import Wallet
  File "C:\python3\lib\site-packages\electrum\wallet.py", line 53, in <module>
    from .bip32 import BIP32Node, convert_bip32_intpath_to_strpath, convert_bip32_strpath_to_intpath
  File "C:\python3\lib\site-packages\electrum\bip32.py", line 11, in <module>
    from . import constants
  File "C:\python3\lib\site-packages\electrum\constants.py", line 30, in <module>
    from . import bitcoin
  File "C:\python3\lib\site-packages\electrum\bitcoin.py", line 35, in <module>
    from . import ecc
  File "C:\python3\lib\site-packages\electrum\ecc.py", line 39, in <module>
    from .ecc_fast import _libsecp256k1, SECP256K1_EC_UNCOMPRESSED
  File "C:\python3\lib\site-packages\electrum\ecc_fast.py", line 151, in <module>
    sys.exit(f"Error: Failed to load libsecp256k1.")
SystemExit: Error: Failed to load libsecp256k1.
🗯 ERROR: build-electrum-git failed
```

Also, the -OO flag is removed from wine python, for similar reasons:
pyinstaller imports electrum, and in electrum/__init__.py, we raise
if -O is used: 9b1fb0e5fe/electrum/__init__.py (L40)
2023-06-02 22:37:43 +00:00

158 lines
6.5 KiB
Python

# taken (with minor modifications) from pycoin
# https://github.com/richardkiss/pycoin/blob/01b1787ed902df23f99a55deb00d8cd076a906fe/pycoin/ecdsa/native/secp256k1.py
import os
import sys
import traceback
import ctypes
from ctypes import (
byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer,
CFUNCTYPE, POINTER, cast
)
from .logging import get_logger
_logger = get_logger(__name__)
SECP256K1_FLAGS_TYPE_MASK = ((1 << 8) - 1)
SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0)
SECP256K1_FLAGS_TYPE_COMPRESSION = (1 << 1)
# /** The higher bits contain the actual data. Do not use directly. */
SECP256K1_FLAGS_BIT_CONTEXT_VERIFY = (1 << 8)
SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9)
SECP256K1_FLAGS_BIT_COMPRESSION = (1 << 8)
# /** Flags to pass to secp256k1_context_create. */
SECP256K1_CONTEXT_VERIFY = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY)
SECP256K1_CONTEXT_SIGN = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN)
SECP256K1_CONTEXT_NONE = (SECP256K1_FLAGS_TYPE_CONTEXT)
SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION)
SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION)
class LibModuleMissing(Exception): pass
def load_library():
# note: for a mapping between bitcoin-core/secp256k1 git tags and .so.V libtool version numbers,
# see https://github.com/bitcoin-core/secp256k1/pull/1055#issuecomment-1227505189
tested_libversions = [2, 1, 0, ] # try latest version first
libnames = []
if sys.platform == 'darwin':
for v in tested_libversions:
libnames.append(f"libsecp256k1.{v}.dylib")
elif sys.platform in ('windows', 'win32'):
for v in tested_libversions:
libnames.append(f"libsecp256k1-{v}.dll")
elif 'ANDROID_DATA' in os.environ:
libnames = ['libsecp256k1.so', ] # don't care about version number. we built w/e is available.
else: # desktop Linux and similar
for v in tested_libversions:
libnames.append(f"libsecp256k1.so.{v}")
# maybe we could fall back to trying "any" version? maybe guarded with an env var?
#libnames.append(f"libsecp256k1.so")
library_paths = []
for libname in libnames: # try local files in repo dir first
library_paths.append(os.path.join(os.path.dirname(__file__), libname))
for libname in libnames:
library_paths.append(libname)
exceptions = []
secp256k1 = None
for libpath in library_paths:
try:
secp256k1 = ctypes.cdll.LoadLibrary(libpath)
except BaseException as e:
exceptions.append(e)
else:
break
if not secp256k1:
_logger.error(f'libsecp256k1 library failed to load. exceptions: {repr(exceptions)}')
return None
try:
secp256k1.secp256k1_context_create.argtypes = [c_uint]
secp256k1.secp256k1_context_create.restype = c_void_p
secp256k1.secp256k1_context_randomize.argtypes = [c_void_p, c_char_p]
secp256k1.secp256k1_context_randomize.restype = c_int
secp256k1.secp256k1_ec_pubkey_create.argtypes = [c_void_p, c_void_p, c_char_p]
secp256k1.secp256k1_ec_pubkey_create.restype = c_int
secp256k1.secp256k1_ecdsa_sign.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p, c_void_p, c_void_p]
secp256k1.secp256k1_ecdsa_sign.restype = c_int
secp256k1.secp256k1_ecdsa_verify.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p]
secp256k1.secp256k1_ecdsa_verify.restype = c_int
secp256k1.secp256k1_ec_pubkey_parse.argtypes = [c_void_p, c_char_p, c_char_p, c_size_t]
secp256k1.secp256k1_ec_pubkey_parse.restype = c_int
secp256k1.secp256k1_ec_pubkey_serialize.argtypes = [c_void_p, c_char_p, c_void_p, c_char_p, c_uint]
secp256k1.secp256k1_ec_pubkey_serialize.restype = c_int
secp256k1.secp256k1_ecdsa_signature_parse_compact.argtypes = [c_void_p, c_char_p, c_char_p]
secp256k1.secp256k1_ecdsa_signature_parse_compact.restype = c_int
secp256k1.secp256k1_ecdsa_signature_normalize.argtypes = [c_void_p, c_char_p, c_char_p]
secp256k1.secp256k1_ecdsa_signature_normalize.restype = c_int
secp256k1.secp256k1_ecdsa_signature_serialize_compact.argtypes = [c_void_p, c_char_p, c_char_p]
secp256k1.secp256k1_ecdsa_signature_serialize_compact.restype = c_int
secp256k1.secp256k1_ecdsa_signature_parse_der.argtypes = [c_void_p, c_char_p, c_char_p, c_size_t]
secp256k1.secp256k1_ecdsa_signature_parse_der.restype = c_int
secp256k1.secp256k1_ecdsa_signature_serialize_der.argtypes = [c_void_p, c_char_p, c_void_p, c_char_p]
secp256k1.secp256k1_ecdsa_signature_serialize_der.restype = c_int
secp256k1.secp256k1_ec_pubkey_tweak_mul.argtypes = [c_void_p, c_char_p, c_char_p]
secp256k1.secp256k1_ec_pubkey_tweak_mul.restype = c_int
secp256k1.secp256k1_ec_pubkey_combine.argtypes = [c_void_p, c_char_p, c_void_p, c_size_t]
secp256k1.secp256k1_ec_pubkey_combine.restype = c_int
# --enable-module-recovery
try:
secp256k1.secp256k1_ecdsa_recover.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p]
secp256k1.secp256k1_ecdsa_recover.restype = c_int
secp256k1.secp256k1_ecdsa_recoverable_signature_parse_compact.argtypes = [c_void_p, c_char_p, c_char_p, c_int]
secp256k1.secp256k1_ecdsa_recoverable_signature_parse_compact.restype = c_int
except (OSError, AttributeError):
raise LibModuleMissing('libsecp256k1 library found but it was built '
'without required module (--enable-module-recovery)')
secp256k1.ctx = secp256k1.secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY)
ret = secp256k1.secp256k1_context_randomize(secp256k1.ctx, os.urandom(32))
if not ret:
_logger.error('secp256k1_context_randomize failed')
return None
return secp256k1
except (OSError, AttributeError) as e:
_logger.error(f'libsecp256k1 library was found and loaded but there was an error when using it: {repr(e)}')
return None
_libsecp256k1 = None
try:
_libsecp256k1 = load_library()
except BaseException as e:
_logger.error(f'failed to load libsecp256k1: {repr(e)}')
if _libsecp256k1 is None:
# hard fail:
raise ImportError("Failed to load libsecp256k1")
def version_info() -> dict:
return {
"libsecp256k1.path": _libsecp256k1._name if _libsecp256k1 else None,
}