Haven't checked if electrum-ecc compiles libsecp reproducibly.
For now let's just keep the old flow.
(but if we spent time on making that compilation reproducible,
the appimage and the macos builds could use it directly)
setup exe used to install Electrum to `C:\Program Files (x86)\Electrum`,
but now as the binaries are amd64, we should install to `C:\Program Files\Electrum`.
With this change, based on my experiments, looks like if there is an existing install,
nsis will keep using that path, but if it's a fresh install, it will now use the 64-bit path.
follow-up fcc4e1d387
Looks like upstream key file changed. Still the same crypto key, just updated expiration date.
```
$ sha256sum winehq_20*
78b185fabdb323971d13bd329fefc8038e08559aa51c4996de18db0639a51df6 *winehq_2019.key
d965d646defe94b3dfba6d5b4406900ac6c81065428bf9d9303ad7a72ee8d1b8 *winehq_2024.key
$ gpg winehq_2019.key
gpg: WARNING: no command supplied. Trying to guess what you mean ...
pub rsa3072 2018-12-10 [SC]
D43F640145369C51D786DDEA76F1A20FF987672F
uid WineHQ packages <wine-devel@winehq.org>
sub rsa3072 2018-12-10 [E] [expired: 2020-12-09]
$ gpg winehq_2024.key
gpg: WARNING: no command supplied. Trying to guess what you mean ...
pub rsa3072 2018-12-10 [SC]
D43F640145369C51D786DDEA76F1A20FF987672F
uid WineHQ packages <wine-devel@winehq.org>
sub rsa3072 2018-12-10 [E]
```
Co-authored-by: SomberNight <somber.night@protonmail.com>
Ah ok, I give up for now... the prev does not really work.
The prior commit works on Windows but not on macOS.
On Windows, it would package all plugins as code and only as code.
On MacOS however, it would not package any plugins at all. And with this commit,
where I mark the plugins folder to be packaged as *data*, it packages all plugins as *both* code and data.
Not sure why.
Let's just package all plugins as both code and data, and ignore the code instances explicitly...
The hw_wallet and jade plugins were being included twice in the pyinstaller binaries.
They were apparently the only two plugins being picked as "modules" (a.pure),
which by default are included as compiled-bytecode.
In addition, we included "electrum/plugins" as data (a.data), which meant all
plugins in source form.
Instead of hacking around to fix the specific issue, this attempts a larger clean-up.
```
602 WARNING: Failed to collect submodules for 'pkg_resources._vendor.pyparsing.diagram' because importing 'pkg_resources._vendor.pyparsing.diagram' raised: ModuleNotFoundError: No module named 'railroad'
libsecp256k1 library failed to load. exceptions: [FileNotFoundError("Could not find module 'C:\\python3\\lib\\site-packages\\electrum\\libsecp256k1-2.dll' (or one of its dependencies). 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 dependencies). 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 dependencies). Try using the full path with constructor syntax."), FileNotFoundError("Could not find module 'libsecp256k1-2.dll' (or one ofits 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.")]
libsecp256k1 library failed to load. exceptions: [FileNotFoundError("Could not find module 'C:\\python3\\lib\\site-packages\\electrum\\libsecp256k1-2.dll' (or one of its dependencies). 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 dependencies). 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 dependencies). Try using the full path with constructor syntax."), FileNotFoundError("Could not find module 'libsecp256k1-2.dll' (or one ofits 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.")]
libsecp256k1 library failed to load. exceptions: [FileNotFoundError("Could not find module 'C:\\python3\\lib\\site-packages\\electrum\\libsecp256k1-2.dll' (or one of its dependencies). 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 dependencies). 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 dependencies). Try using the full path with constructor syntax."), FileNotFoundError("Could not find module 'libsecp256k1-2.dll' (or one ofits 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.")]
5921 WARNING: collect_data_files - skipping data collection for module 'electrum.plugins' as it is not a package.
```
pyinstaller tries to import electrum and its different submodules at build-time
during the "Analysis" phase. sys._GUI_QT_VERSION was not getting set there,
and the resulting exception was blocking pyinstaller from discovering that
gui/common_qt is being used.
at runtime:
```
$ ./dist/Electrum.app/Contents/MacOS/run_electrum
1.53 | E | daemon.Daemon | GUI raised exception: Exception('Error loading trustedcoin plugin: ModuleNotFoundError("No module named \'electrum.gui.common_qt\'")'). shutting down.
1.53 | E | __main__ | daemon.run_gui errored
Traceback (most recent call last):
File "electrum/plugin.py", line 135, in load_plugin
spec.loader.exec_module(module)
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/Users/vagrant/electrum/dist/Electrum.app/Contents/MacOS/electrum/plugins/trustedcoin/qt.py", line 51, in <module>
from .common_qt import TrustedcoinPluginQObject
File "/Users/vagrant/electrum/dist/Electrum.app/Contents/MacOS/electrum/plugins/trustedcoin/common_qt.py", line 16, in <module>
from electrum.gui.common_qt.plugins import PluginQObject
ModuleNotFoundError: No module named 'electrum.gui.common_qt'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "run_electrum", line 456, in handle_cmd
d.run_gui()
File "electrum/daemon.py", line 617, in run_gui
self.gui_object = gui.ElectrumGui(config=self.config, daemon=self, plugins=self._plugins)
File "electrum/util.py", line 473, in do_profile
o = func(*args, **kw_args)
File "electrum/gui/qt/__init__.py", line 153, in __init__
self.plugins.load_plugin('trustedcoin')
File "electrum/plugin.py", line 138, in load_plugin
raise Exception(f"Error loading {name} plugin: {repr(e)}") from e
Exception: Error loading trustedcoin plugin: ModuleNotFoundError("No module named 'electrum.gui.common_qt'")
```
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)
- repro builds to use fixed uid=1000 inside the container
- in case the file permissions leak into the binaries, they are still reproducible
- chown 1000:1000 fresh_clone
- repro builds to create fresh_clone dir outside git clone
- otherwise the local dev build would still interact with the fresh_clone dir
- due to e.g. recursive "find -exec touch",
- and even the "docker build" cmd itself would try to stat/read it
- see https://github.com/docker/for-linux/issues/380
- and "rm -rf fresh_clone" needs sudo if the host uid is not 1000
- this way the local dev build does not need sudo
to recap:
- local dev builds use the host userid inside the container, directly operate on the project dir
- does not need sudo
- repro builds create a fresh git clone, chown it to 1000, and use userid=1000 inside the container
- if the host userid is 1000, does not need sudo
- otherwise, needs sudo
closes https://github.com/spesmilo/electrum/issues/8261
reproducibility probably needs a hardcoded userid
Also, move the UID arg later in the dockerfiles, for better caching.
(if local dev build and repro build set different UIDs, the build caches
will diverge at that step)
The .dockerignore symlink in the project root dir is only picked up by the android build.
The android build has the project root as its build context for "docker build" --
the other builds have their own subdirectories as build context, e.g. contrib/build-linux/appimage.
- follow-up prev: CONTRIB was not defined
- rm folder signed/stripped if already exists (otherwise script early-exited silently)
- quote paths to guard against whitespace shenanigans
note: python 3.9.x is now in source-only mode, so could not update to latest...
it is time to investigate upgrading to python 3.10 in the win and mac binaries