upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-08-19 18:17:16 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-08-23 04:37:36 +0000
commit8f8a02e8ea3358ddec043bb9b1f615d0d1fc9fc7 (patch)
tree00f4c8247b2c90825529d03e1272f05251d8d23c
parenta7744058c49b1ba2c605f9e8380d9c3e8665bbc0 (diff)
build: pin the dependencies that decide consensus, and check what we run
The two dependency clones were `git clone --depth 1 <url>` with no revision, which resolves to whatever the default branch points at the moment the build happens to run. For RandomX that is the proof of work. Its master is not frozen -- v2.0 changed the algorithm in March -- so two builds of the same Bitflash commit, made weeks apart, can hash the same header differently. That is not a supply-chain worry, it is a chain split delivered as a build artifact, with no version recorded anywhere to explain it afterwards. For libsecp256k1 it is signature verification, the rule deciding who may spend. Both now fetch a full commit id, which is the only form here that verifies what it got, since git resolves the object by its own hash. The RandomX pin is the commit this tree has been building and syncing against, so today's behaviour is unchanged; secp256k1 is pinned to the v0.8.0 release commit. appimagetool came from the "continuous" tag, which upstream moves in place on every push, fetched over the network and executed unverified. Pinned to a numbered release and checked by digest before it is allowed to run. It also ran from /tmp on a fixed name, guarded by `[ ! -x /tmp/appimagetool ]` -- an executable already sitting there is taken as the tool, so any local account could leave one and have it run as whoever built. The AppDir had the same shape one step later, through symlinks on the rm -rf. Both moved under the build tree, which the build already owns, and cleaned by `make clean`. (cherry picked from commit 664aebca08d17a9dbae12c25f21cd8ef2abe7aa6)
-rw-r--r--Makefile108
1 files changed, 85 insertions, 23 deletions
diff --git a/Makefile b/Makefile
index ea720f1..abd75c5 100644
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,40 @@ NPROC := $(shell nproc 2>/dev/null || echo 2)
12SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") 12SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo")
13VERSION := 1.2.15 13VERSION := 1.2.15
14 14
15# ---- Pinned third-party sources -------------------------------------------
16#
17# These were `git clone --depth 1 <url>` with no revision, which resolves to
18# whatever the default branch happens to point at the moment the build runs.
19# For a dependency that only had to link, that is untidy. For these two it is
20# not:
21#
22# RandomX is the proof of work. Its master is not frozen -- v2.0 (Mar 2026)
23# changed the algorithm -- so two builds of the same Bitflash commit, made a
24# few weeks apart, can compute different hashes for the same header. That is
25# not a supply-chain worry, it is a chain split arriving as a build artifact,
26# with no version recorded anywhere to explain it afterwards.
27#
28# libsecp256k1 is signature verification, i.e. the rule deciding who may
29# spend. Whatever is on master on the day of the build is what enforces it.
30#
31# Pinned to full commit ids, not tags: a tag is a mutable pointer, and `git
32# checkout <sha>` is the only form here that verifies what it fetched (git
33# resolves the object by its own hash). Bump deliberately, and rebuild and
34# resync before shipping the result.
35#
36# RandomX pin is the commit this tree has been building and syncing against
37# (post-v2.0.1 master, 2026-05-24) -- chosen to change nothing today.
38SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1
39SECP256K1_COMMIT := 6e2c8bc4ecdc6e71dbe7a368f360d8d453ce435d
40RANDOMX_REPO := https://github.com/tevador/RandomX
41RANDOMX_COMMIT := 1e9d4b2df63fa6edf46b06789486e23c0fcaa55a
42
43# appimagetool came from the "continuous" release, a tag that is moved in place
44# on every upstream push, fetched over the network and executed. Pinned to a
45# numbered release and checked by digest before it is allowed to run.
46APPIMAGETOOL_URL := https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-x86_64.AppImage
47APPIMAGETOOL_SHA256 := ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0
48
15# ---- Linux ---------------------------------------------------------------- 49# ---- Linux ----------------------------------------------------------------
16 50
17linux: deps-linux 51linux: deps-linux
@@ -47,8 +81,12 @@ deps-secp256k1:
47 @if [ ! -f /usr/local/lib/libsecp256k1.a ]; then \ 81 @if [ ! -f /usr/local/lib/libsecp256k1.a ]; then \
48 echo "==> building libsecp256k1"; \ 82 echo "==> building libsecp256k1"; \
49 rm -rf $(ROOT)/secp256k1-build; \ 83 rm -rf $(ROOT)/secp256k1-build; \
50 git clone --depth 1 https://github.com/bitcoin-core/secp256k1 $(ROOT)/secp256k1-build; \ 84 git init -q $(ROOT)/secp256k1-build; \
51 cd $(ROOT)/secp256k1-build && ./autogen.sh && \ 85 cd $(ROOT)/secp256k1-build && \
86 git remote add origin $(SECP256K1_REPO) && \
87 git fetch -q --depth 1 origin $(SECP256K1_COMMIT) && \
88 git checkout -q $(SECP256K1_COMMIT) && \
89 ./autogen.sh && \
52 ./configure --enable-module-schnorrsig --enable-module-extrakeys \ 90 ./configure --enable-module-schnorrsig --enable-module-extrakeys \
53 --disable-shared --with-pic --disable-benchmark --disable-tests && \ 91 --disable-shared --with-pic --disable-benchmark --disable-tests && \
54 make -j$(NPROC) && $(SUDO) make install && $(SUDO) ldconfig; \ 92 make -j$(NPROC) && $(SUDO) make install && $(SUDO) ldconfig; \
@@ -61,7 +99,11 @@ deps-randomx:
61 @if [ ! -f $(HOME)/RandomX/build/librandomx.a ]; then \ 99 @if [ ! -f $(HOME)/RandomX/build/librandomx.a ]; then \
62 echo "==> building RandomX"; \ 100 echo "==> building RandomX"; \
63 rm -rf $(HOME)/RandomX; \ 101 rm -rf $(HOME)/RandomX; \
64 git clone --depth 1 https://github.com/tevador/RandomX $(HOME)/RandomX; \ 102 git init -q $(HOME)/RandomX; \
103 cd $(HOME)/RandomX && \
104 git remote add origin $(RANDOMX_REPO) && \
105 git fetch -q --depth 1 origin $(RANDOMX_COMMIT) && \
106 git checkout -q $(RANDOMX_COMMIT); \
65 mkdir -p $(HOME)/RandomX/build; \ 107 mkdir -p $(HOME)/RandomX/build; \
66 cd $(HOME)/RandomX/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \ 108 cd $(HOME)/RandomX/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \
67 make -j$(NPROC) randomx; \ 109 make -j$(NPROC) randomx; \
@@ -70,37 +112,57 @@ deps-randomx:
70 echo "==> RandomX already built"; \ 112 echo "==> RandomX already built"; \
71 fi 113 fi
72 114
115# APPDIR and the tool both used fixed paths under /tmp, on a directory every
116# local account can write. `[ ! -x /tmp/appimagetool ]` means an executable
117# already sitting at that name is taken as the tool and run, so anyone with a
118# shell on the build machine could have put one there first and had it execute
119# as whoever ran make; `rm -rf /tmp/bitflash.AppDir` then mkdir is the same
120# problem one step later, through symlinks. Both now live under the build tree,
121# which the build already owns.
122APPDIR := $(ROOT)/build/bitflash.AppDir
123APPIMAGETOOL := $(ROOT)/build/appimagetool
124
73appimage: src/bitflash 125appimage: src/bitflash
74 @echo "==> building AppImage" 126 @echo "==> building AppImage"
75 @if [ ! -x /tmp/appimagetool ]; then \ 127 @mkdir -p $(ROOT)/build
76 wget -q "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" \ 128 @if [ ! -x "$(APPIMAGETOOL)" ]; then \
77 -O /tmp/appimagetool && chmod +x /tmp/appimagetool; \ 129 echo " fetching appimagetool"; \
130 wget -q "$(APPIMAGETOOL_URL)" -O "$(APPIMAGETOOL).tmp" || \
131 { echo " ERROR: appimagetool download failed"; rm -f "$(APPIMAGETOOL).tmp"; exit 1; }; \
132 echo "$(APPIMAGETOOL_SHA256) $(APPIMAGETOOL).tmp" | sha256sum -c - >/dev/null 2>&1 || \
133 { echo " ERROR: appimagetool digest mismatch, refusing to run it"; \
134 echo " expected $(APPIMAGETOOL_SHA256)"; \
135 echo " got $$(sha256sum "$(APPIMAGETOOL).tmp" | cut -d" " -f1)"; \
136 rm -f "$(APPIMAGETOOL).tmp"; exit 1; }; \
137 chmod +x "$(APPIMAGETOOL).tmp" && mv "$(APPIMAGETOOL).tmp" "$(APPIMAGETOOL)"; \
78 fi 138 fi
79 @rm -rf /tmp/bitflash.AppDir 139 @rm -rf $(APPDIR)
80 @mkdir -p /tmp/bitflash.AppDir/usr/bin \ 140 @mkdir -p $(APPDIR)/usr/bin \
81 /tmp/bitflash.AppDir/usr/lib \ 141 $(APPDIR)/usr/lib \
82 /tmp/bitflash.AppDir/usr/share/applications \ 142 $(APPDIR)/usr/share/applications \
83 /tmp/bitflash.AppDir/usr/share/icons/hicolor/256x256/apps 143 $(APPDIR)/usr/share/icons/hicolor/256x256/apps
84 @cp src/bitflash /tmp/bitflash.AppDir/usr/bin/bitflash 144 @cp src/bitflash $(APPDIR)/usr/bin/bitflash
85 @printf '#!/bin/sh\nHERE="$$(dirname "$$(readlink -f "$$0")")"\nexport LD_LIBRARY_PATH="$$HERE/usr/lib:$$LD_LIBRARY_PATH"\nexec "$$HERE/usr/bin/bitflash" "$$@"\n' \ 145 @printf '#!/bin/sh\nHERE="$$(dirname "$$(readlink -f "$$0")")"\nexport LD_LIBRARY_PATH="$$HERE/usr/lib:$$LD_LIBRARY_PATH"\nexec "$$HERE/usr/bin/bitflash" "$$@"\n' \
86 > /tmp/bitflash.AppDir/AppRun && chmod +x /tmp/bitflash.AppDir/AppRun 146 > $(APPDIR)/AppRun && chmod +x $(APPDIR)/AppRun
87 @printf '[Desktop Entry]\nName=Bitflash\nExec=bitflash\nIcon=bitflash\nType=Application\nCategories=Finance;\n' \ 147 @printf '[Desktop Entry]\nName=Bitflash\nExec=bitflash\nIcon=bitflash\nType=Application\nCategories=Finance;\n' \
88 > /tmp/bitflash.AppDir/bitflash.desktop 148 > $(APPDIR)/bitflash.desktop
89 @cp /tmp/bitflash.AppDir/bitflash.desktop \ 149 @cp $(APPDIR)/bitflash.desktop \
90 /tmp/bitflash.AppDir/usr/share/applications/ 150 $(APPDIR)/usr/share/applications/
91 @python3 -c "\ 151 @APPDIR=$(APPDIR) python3 -c "\
152import os; \
92from PIL import Image; \ 153from PIL import Image; \
154d = os.environ['APPDIR']; \
93ico = Image.open('src/rc/bitcoin.ico'); \ 155ico = Image.open('src/rc/bitcoin.ico'); \
94img = ico.convert('RGBA'); \ 156img = ico.convert('RGBA'); \
95img.save('/tmp/bitflash.AppDir/bitflash.png'); \ 157img.save(d + '/bitflash.png'); \
96import shutil; shutil.copy('/tmp/bitflash.AppDir/bitflash.png', \ 158import shutil; shutil.copy(d + '/bitflash.png', \
97'/tmp/bitflash.AppDir/usr/share/icons/hicolor/256x256/apps/bitflash.png')" 159d + '/usr/share/icons/hicolor/256x256/apps/bitflash.png')"
98 @for lib in libsodium.so.23 libdb_cxx-5.3.so libglfw.so.3; do \ 160 @for lib in libsodium.so.23 libdb_cxx-5.3.so libglfw.so.3; do \
99 path=$$(ldconfig -p | grep " $$lib " | awk '{print $$NF}' | head -1); \ 161 path=$$(ldconfig -p | grep " $$lib " | awk '{print $$NF}' | head -1); \
100 [ -z "$$path" ] && path=$$(find /usr/lib /lib -name "$$lib" 2>/dev/null | head -1); \ 162 [ -z "$$path" ] && path=$$(find /usr/lib /lib -name "$$lib" 2>/dev/null | head -1); \
101 [ -n "$$path" ] && cp -L "$$path" /tmp/bitflash.AppDir/usr/lib/ && echo " bundled $$lib" || echo " missing $$lib"; \ 163 [ -n "$$path" ] && cp -L "$$path" $(APPDIR)/usr/lib/ && echo " bundled $$lib" || echo " missing $$lib"; \
102 done 164 done
103 @ARCH=x86_64 /tmp/appimagetool --no-appstream /tmp/bitflash.AppDir \ 165 @ARCH=x86_64 $(APPIMAGETOOL) --no-appstream $(APPDIR) \
104 $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage 2>&1 | grep -E "^Built|^Error" || true 166 $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage 2>&1 | grep -E "^Built|^Error" || true
105 @echo "Built: Bitflash-$(VERSION)-x86_64.AppImage" 167 @echo "Built: Bitflash-$(VERSION)-x86_64.AppImage"
106 168
@@ -157,7 +219,7 @@ clean:
157 $(MAKE) -C src -f Makefile clean 2>/dev/null || true 219 $(MAKE) -C src -f Makefile clean 2>/dev/null || true
158 cd src && make -f makefile.mingw clean 2>/dev/null || true 220 cd src && make -f makefile.mingw clean 2>/dev/null || true
159 rm -f Bitflash-*.AppImage Bitflash-*.zip 221 rm -f Bitflash-*.AppImage Bitflash-*.zip
160 rm -rf Bitflash-*-windows 222 rm -rf Bitflash-*-windows build
161 223
162tests: 224tests:
163 $(MAKE) -C src -f Makefile tests 225 $(MAKE) -C src -f Makefile tests