Skip to content

Commit efdf877

Browse files
committed
Fix Paper Wallet handling
1 parent b800dda commit efdf877

9 files changed

Lines changed: 167 additions & 81 deletions

File tree

Makefile

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ SHELL = /bin/bash
1313

1414
# Change to your own Apple Developer ID, if you want to code-sign the resultant .app
1515

16-
ALL = gui,serial,wallet,invoice
16+
MIN = gui,wallet
17+
ALL = gui,wallet,serial,invoice
1718

1819
APPLEID ?= perry@kundert.ca
1920
TEAMID ?= ZD8TVTCXDS
@@ -90,7 +91,7 @@ VENV_OPTS = --system-site-packages --copies # make available references some sys
9091
all: help
9192

9293
help:
93-
@echo "GNUmakefile for cpppo. Targets:"
94+
@echo "GNUmakefile for python-slip39. Targets:"
9495
@echo " help This help"
9596
@echo " test Run unit tests under Python3"
9697
@echo " clean Remove build artifacts"
@@ -99,7 +100,17 @@ help:
99100
@echo " upload Upload new version to pypi (package maintainer only)"
100101
@echo " app Build the macOS SLIP-39.app"
101102
@echo " installer Build the .dmg, .msi, as appropriate for PLATFORM"
102-
@echo " print-PLATFORM prints the detected PLATFORM"
103+
@echo
104+
@echo " nix-venv Create and/or start Nix-supplied Python virtual env"
105+
@echo " nix-venv-test Run the 'make test' target within the Nix Python venv"
106+
@echo " TARGET=py313 make nix-venv... Use a Python 3.13 Nix environment for the remaining targets"
107+
@echo " PATH=/usr/local/bin:$PATH make venv... Use an installed Python environment for the remaining targets"
108+
109+
110+
# Installs ALL optional Python requirements for testing
111+
.PHONY: deps-test
112+
deps-test: install-all \
113+
slip39/payments_test/slip-39-app.crypto-license
103114

104115
test: deps-test
105116
$(PYTEST) $(PYTEST_OPTS)
@@ -143,7 +154,11 @@ clean:
143154

144155
nix-%:
145156
@if [ -r flake.nix ]; then \
146-
nix develop $(NIX_OPTS) --command make $*; \
157+
if [ -n "$(TARGET)" ]; then \
158+
nix develop .#$(TARGET) $(NIX_OPTS) --command make $*; \
159+
else \
160+
nix develop $(NIX_OPTS) --command make $*; \
161+
fi; \
147162
else \
148163
nix-shell $(NIX_OPTS) --run "make $*"; \
149164
fi
@@ -158,7 +173,6 @@ print-%:
158173
@echo $*\'s origin is $(origin $*)
159174

160175

161-
162176
#
163177
# org-mode products.
164178
#
@@ -365,9 +379,6 @@ $(PAY-TEST-LIC): GRANTS="{\"crypto-licensing-server\": {\
365379
}}"
366380

367381

368-
.PHONY: deps-test
369-
deps-test: slip39/payments_test/slip-39-app.crypto-license
370-
371382
# Try to copy the generated slip-39-app.crypto-license, if it exists, but no worries if it doesn't
372383
slip39/payments_test/slip-39-app.crypto-license: FORCE
373384
cp $(SLIP-39-LIC) $@ 2>/dev/null || echo "Missing $(SLIP-39-LIC); ignoring..."
@@ -415,6 +426,7 @@ venv: $(VENV)
415426
@echo; echo "*** Activating $< VirtualEnv for Interactive $(SHELL)"
416427
@bash --init-file $</bin/activate -i
417428

429+
# Installs the MIN optional Python requirements to support GUI, paper wallets
418430
$(VENV):
419431
@[[ "$(PYTHON_V)" =~ "^venv" ]] && ( echo -e "\n\n!!! $@ Cannot start a venv within a venv"; false ) || true
420432
@echo; echo "*** Building $@ VirtualEnv..."
@@ -431,6 +443,9 @@ $(WHEEL): install-dev FORCE
431443

432444
# Install from wheel, including all optional extra dependencies (except dev). Always use the venv (or global)
433445
install: $(WHEEL) FORCE
446+
$(PYTHON) -m pip install --no-user --force-reinstall $<[$(MIN)]
447+
448+
install-all:
434449
$(PYTHON) -m pip install --no-user --force-reinstall $<[$(ALL)]
435450

436451
install-%: # ...-dev, -tests, -gui, -serial, -wallet, -invoice
@@ -909,6 +924,7 @@ app-assess: dist/SLIP-39.app
909924
#
910925
#
911926
# The --onefile approach is incompatible with macOS Apps; use --onedir
927+
# Ensures various Python packages using shared libraries are made available
912928
SLIP-39-macOS.spec: SLIP-39.py
913929
@echo -e "\n\n!!! Rebuilding $@; Must be manually edited..."
914930
pyinstaller --noconfirm --windowed --onedir \
@@ -917,6 +933,13 @@ SLIP-39-macOS.spec: SLIP-39.py
917933
--collect-data shamir_mnemonic \
918934
--collect-all tzdata \
919935
--collect-all zoneinfo \
936+
--collect-all pycryptodome \
937+
--collect-all eth_account \
938+
--hidden-import Crypto \
939+
--hidden-import Crypto.Cipher \
940+
--hidden-import Crypto.Protocol \
941+
--hidden-import Crypto.Protocol.KDF \
942+
--hidden-import Crypto.Hash \
920943
--hidden-import slip39 \
921944
--collect-data slip39 \
922945
--osx-entitlements-file SLIP-39.metadata/entitlements.plist \

SLIP-39-macOS.spec

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,19 @@ from PyInstaller.utils.hooks import collect_all
44

55
datas = []
66
binaries = []
7-
hiddenimports = ['slip39', 'tzdata']
7+
hiddenimports = ['Crypto', 'Crypto.Cipher', 'Crypto.Protocol', 'Crypto.Protocol.KDF', 'Crypto.Hash', 'slip39']
88
datas += collect_data_files('shamir_mnemonic')
99
datas += collect_data_files('slip39')
1010
tmp_ret = collect_all('tzdata')
1111
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
1212
tmp_ret = collect_all('zoneinfo')
1313
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
14+
tmp_ret = collect_all('Crypto')
15+
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
16+
tmp_ret = collect_all('eth_account')
17+
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
18+
tmp_ret = collect_all('py_ecc')
19+
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
1420

1521

1622
a = Analysis(
@@ -59,15 +65,14 @@ app = BUNDLE(
5965
coll,
6066
name='SLIP-39.app',
6167
icon='images/SLIP-39.icns',
62-
version='14.0.2',
6368
info_plist={
6469
'NSPrincipalClass': 'NSApplication',
6570
'NSAppleScriptEnabled': False,
6671
'LSBackgroundOnly': False,
6772
'NSRequiresAquaSystemAppearance': 'No',
6873
'CFBundleSupportedPlatforms': ['MacOSX'],
6974
'CFBundleIdentifier': 'ca.kundert.perry.SLIP39',
70-
'CFBundleVersion': '14.0.2',
75+
'CFBundleVersion': '14.1.0',
7176
'CFBundlePackageType':'APPL',
7277
'LSApplicationCategoryType':'public.app-category.utilities',
7378
'LSMinimumSystemVersion':'10.15',

flake.nix

Lines changed: 83 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,60 +13,100 @@
1313

1414
# Create Python environments with required packages
1515
mkPythonEnv = pythonPkg: pythonPkg.withPackages (ps: with ps; [
16-
tkinter
1716
pytest
18-
#coincurve scikit-learn scikit-build cmake
19-
#pycryptodome
20-
#pynacl
17+
pip
18+
tkinter
19+
coincurve scikit-learn scikit-build cmake
20+
pycryptodome
21+
pynacl
2122
]);
2223

24+
python39Env = mkPythonEnv pkgs.python39;
2325
python310Env = mkPythonEnv pkgs.python310;
2426
python311Env = mkPythonEnv pkgs.python311;
2527
python312Env = mkPythonEnv pkgs.python312;
2628
python313Env = mkPythonEnv pkgs.python313;
2729
python314Env = mkPythonEnv pkgs.python314;
28-
python3Env = mkPythonEnv pkgs.python3;
30+
python3Env = mkPythonEnv pkgs.python3;
31+
pypy310Env = mkPythonEnv pkgs.pypy310;
32+
pypy3Env = mkPythonEnv pkgs.pypy3;
33+
34+
# Common build inputs for all dev shells
35+
commonInputs = with pkgs; [
36+
# Common tools
37+
cacert
38+
git
39+
gnumake
40+
openssh
41+
bash
42+
bash-completion
43+
which
44+
45+
# coincurve + skikit-learn requires this to build:
46+
cmake clang ninja pkg-config
2947

48+
# Utilities for creating MacOS .dmg
49+
nodejs_20 # Not a bleeding-edge version
50+
];
51+
52+
commonShellHook = ''
53+
echo "Welcome to the Crypto Licensing multi-Python development environment!"
54+
echo "Available Python interpreters:"
55+
echo ""
56+
for cmd in python python3.9 python3.10 python3.11 python3.12 python3.13 python3.14 pypy3 pypy3.10; do
57+
printf "%-12s: %-20.19s: %s\n" "$cmd" "$($cmd --version 2>/dev/null || echo "(unavailable)")" "$(which $cmd 2>/dev/null)"
58+
done
59+
echo ""
60+
echo "All versions have pytest, pip, tkinter, coincurve, pycryptodome, and pynacl installed."
61+
echo "Use 'make test' to run tests with the default Python version."
62+
'';
63+
64+
# Create a dev shell with specific Python environment(s) and optional extras
65+
mkDevShell = { pythonEnvs, extraInputs ? [], shellHook ? commonShellHook}: pkgs.mkShell {
66+
buildInputs = commonInputs ++ pythonEnvs ++ extraInputs;
67+
inherit shellHook;
68+
};
3069
in {
3170
# Single development shell with all Python versions
32-
devShells.default = pkgs.mkShell {
33-
buildInputs = with pkgs; [
34-
# Common tools
35-
cacert
36-
git
37-
gnumake
38-
openssh
39-
bash
40-
bash-completion
41-
42-
# coincurve + skikit-learn requires this to build:
43-
#cmake clang ninja pkg-config
44-
45-
# All Python versions with packages
46-
#python310Env
47-
#python311Env
48-
#python312Env
49-
python313Env
50-
#python314Env
51-
#python3Env
52-
53-
# Utilities for creating MacOS .dmg
54-
nodejs_20 # Not a bleeding-edge version
55-
];
56-
57-
shellHook = ''
58-
echo "Welcome to the multi-Python development environment!"
59-
echo "Available Python interpreters:"
60-
echo " python (default): $(python --version 2>/dev/null || echo 'not available')"
61-
echo " python3: $(python3 --version 2>/dev/null || echo 'not available')"
62-
echo " python3.10: $(python3.10 --version 2>/dev/null || echo 'not available')"
63-
echo " python3.11: $(python3.11 --version 2>/dev/null || echo 'not available')"
64-
echo " python3.12: $(python3.12 --version 2>/dev/null || echo 'not available')"
65-
echo " python3.13: $(python3.13 --version 2>/dev/null || echo 'not available')"
66-
echo " python3.14: $(python3.14 --version 2>/dev/null || echo 'not available')"
67-
echo ""
68-
echo "All versions have pytest, coincurve, pycryptodome, and pynacl installed."
69-
'';
71+
devShells.default = mkDevShell {
72+
pythonEnvs = [ python3Env ];
73+
};
74+
75+
# Individual development shells for specific Python versions
76+
devShells.py39 = mkDevShell {
77+
pythonEnvs = [ python39Env ];
78+
};
79+
80+
devShells.py310 = mkDevShell {
81+
pythonEnvs = [ python310Env ];
82+
};
83+
84+
devShells.py311 = mkDevShell {
85+
pythonEnvs = [ python311Env ];
86+
};
87+
88+
devShells.py312 = mkDevShell {
89+
pythonEnvs = [ python312Env ];
90+
};
91+
92+
devShells.py313 = mkDevShell {
93+
pythonEnvs = [ python313Env ];
94+
};
95+
96+
devShells.py314 = mkDevShell {
97+
pythonEnvs = [ python314Env ];
98+
};
99+
100+
devShells.py3 = mkDevShell {
101+
pythonEnvs = [ python3Env ];
102+
};
103+
104+
devShells.pypy310 = mkDevShell {
105+
pythonEnvs = [ pypy310Env ];
106+
};
107+
108+
devShells.pypy3 = mkDevShell {
109+
pythonEnvs = [ pypy3Env ];
70110
};
71111
});
72112
}

slip39/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
except ImportError as exc:
6969
AES = None
7070
scrypt = None
71-
message = f"Unable to support Paper Wallet output: {exc}"
71+
message = f"Unable to support Paper Wallet output (pycryptodome): {exc}"
7272
warnings.warn( message, ImportWarning )
7373
if log.isEnabledFor( logging.DEBUG ):
7474
log.exception( message )
@@ -78,7 +78,7 @@
7878
import eth_account
7979
except ImportError as exc:
8080
eth_account = None
81-
message = f"Unable to support Paper Wallet output: {exc}"
81+
message = f"Unable to support Paper Wallet output (eth_account): {exc}"
8282
warnings.warn( message, ImportWarning )
8383
if log.isEnabledFor( logging.DEBUG ):
8484
log.exception( message )

slip39/gui/SLIP-39-WALLET.org

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@
22
#+OPTIONS: toc:nil title:nil author:nil
33

44
#+BEGIN_ABSTRACT
5-
Supply a password to produce an encrypted Ethereum JSON wallet or Bitcoin, ... BIP-38 Paper Wallet.
5+
Supply a password (or a hint) to produce an encrypted Ethereum JSON wallet or Bitcoin, ... BIP-38
6+
Paper Wallet.
67

7-
If you import these SLIP-39 Mnemonics directly into your Trezor hardware wallet -- you do
8-
/not/ need Paper Wallets: you have access to /all/ of the wallets, in every cryptocurrency supported
9-
by the Trezor.
8+
If you import these SLIP-39 (or BIP-39) Mnemonics directly into your Trezor hardware wallet -- you
9+
do /not/ need Paper Wallets: you have access to /all/ of the wallets, in every cryptocurrency
10+
supported by the Trezor.
1011

1112
These are intended to support the importing of /individual/, single wallets into standard software
1213
wallets (eg. Brave browser, Metamask plugins, other software wallets on PCs or mobile devices). If
1314
you need some cryptocurrency "walking around" money, use them to create recoverable "Safe Portable
1415
Crypto Accounts" (below).
1516
#+END_ABSTRACT
1617

18+
NOTE: you likely want to change the Custom Derivation Path in "# to Derive:" to something other than
19+
your main wallet at .../0'/0/0: probably a path like =99'/0/0-3=, to create 4 Paper Wallets at a
20+
different "account" (99').
21+
1722
* Password
1823

1924
If you lose or forget this Paper Wallet password -- you cannot import these wallets into

slip39/gui/SLIP-39-WALLET.txt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1-
Supply a password to produce an encrypted Ethereum JSON wallet or
2-
Bitcoin, … BIP-38 Paper Wallet.
1+
Supply a password (or a hint) to produce an encrypted Ethereum JSON
2+
wallet or Bitcoin, … BIP-38 Paper Wallet.
33

4-
If you import these SLIP-39 Mnemonics directly into your Trezor hardware
5-
wallet – you do /not/ need Paper Wallets: you have access to /all/ of
6-
the wallets, in every cryptocurrency supported by the Trezor.
4+
If you import these SLIP-39 (or BIP-39) Mnemonics directly into your
5+
Trezor hardware wallet – you do /not/ need Paper Wallets: you have
6+
access to /all/ of the wallets, in every cryptocurrency supported by the
7+
Trezor.
78

89
These are intended to support the importing of /individual/, single
910
wallets into standard software wallets (eg. Brave browser, Metamask
1011
plugins, other software wallets on PCs or mobile devices). If you need
1112
some cryptocurrency "walking around" money, use them to create
1213
recoverable "Safe Portable Crypto Accounts" (below).
1314

15+
NOTE: you likely want to change the Custom Derivation Path in "# to
16+
Derive:" to something other than your main wallet at …/0'/0/0: probably
17+
a path like `99'/0/0-3', to create 4 Paper Wallets at a different
18+
"account" (99').
19+
1420

1521
1 Password
1622
══════════

0 commit comments

Comments
 (0)