From 6ca1a1d6799474f8ca977b93ab630af7ace879c2 Mon Sep 17 00:00:00 2001 From: Victorio Nascimento <155357371+Vic-Nas@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:45:28 -0400 Subject: Add Linux GUI installer via Wine (#3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Linux GUI installer via Wine * Fix launcher creation and add BTF_RELAY env var support * Pool server, Linux GUI, unified binary, README update * Root Makefile: make linux / make windows, cleaner README * Remove headless.cpp * Fix XPM color count mismatch causing toolbar image errors on Linux * XPM icons: same code on Windows and Linux, no ifdefs around image loading * Fix GTK icon crash and Linux printf format * btfrv: 10s socket timeout on relay connects * Faster peer discovery: more dials per pass, shorter backoff and sleep * Parallel btf peer connections * Fix GetMyExternalIP - was disabled, now uses modern IP echo services * Fix tunnel disconnect on idle and restore external IP detection * Filter stale Nostr descriptors * Sort peers by freshness, fresh first * Pool: add .btf Stratum listener — miners connect via rendezvous, no port forwarding needed * btf pool: self-replacing listeners, one per relay, no queuing between miners * Mining modes: solo/operator/participant — pool server on-demand, participant Stratum client * Status bar: show external IP and .btf address * README: clean rewrite, concept-first, minimal * make linux produces AppImage * make linux produces AppImage * Pool dashboard: connect instructions, tabs, share bars * Perf fixes: GetMyExternalIP threaded, btf listener counted * Perf fixes: GetMyExternalIP threaded, btf listener counted * Fix pool payouts: defer until coinbase maturity * Pool: clean mode switching, IP warning * Pool: clean mode switching * Fix gPoolRunning: remove static * AppImage: use real icon from bitcoin.ico * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Windows build: use mingw32-make * Windows build: simpler make invocation * Add deps-windows target * Windows build fixes * Windows build fixes * Windows makefile: fix obj dir * Windows: output to repo root * Windows: bundle DLLs into zip * Replace wxWidgets with ImGui+GLFW: same build on Linux and Windows * Fix %I64d that slipped back through rebase (main.h, net.h) * MinGW: add _mkdir shim for non-MSVC Windows; fix %I64d * Fix gPoolRunning extern outside ifndef _WIN32 * Remove -lboost_system: boost is header-only in this codebase * Status bar: copy buttons for IP and .btf address * Windows: add app icon via windres, strip wx stuff from rc file * Clean GUI: single Options menu item, bigger font, better spacing, cleaner options dialog; update README * GUI: embed Roboto font at 16px for clear readability on all platforms * Windows: windres depends on obj dir target * Fix balance hidden off-screen: put on own line below address bar * Windows: inline mkdir in every rule, remove dir target that confused make * Windows: move all target to top so it's the default rule * Fix pool server not starting: always start when operator selected, re-sync dialog state on open * Write debug.log to data directory (AppData/Roaming/Bitflash on Windows) * Participant miner: use wallet address as username so payouts go to wallet * Add .gitattributes to lock LF line endings, prevent CRLF drift * Refactor pool mining to btf-only transport * Persist pool settings and startup wiring * Prune stale peers and expose pool queries * Fix build regressions and add CLI mode/arg parity * Fix rpc miner stats declaration order * Centralize pool runtime extern declarations * Separate operator/participant dashboards and restore peer stats * Add live telemetry strip and clearer per-mode runtime metrics * Reduce mining dashboard clutter and remove manual pool entry * Count only authorized pool miners * Seed initial pool job on startup * Use a real share target for pool work * Switch pool accounting to round-based shares * Fix nostr pool announcer stats call sites * Fix pool stats definition order * Improve pool worker status display * Add mutex include for participant status * Replace ImClamp in dashboard layout * Clarify participant work status * Log participant status transitions * Reduce peer discovery log noise * Add participant status badge * Track participant auth acknowledgements * Log and validate pool job delivery --------- Co-authored-by: Bitflash Pool Dev --- Makefile | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Makefile (limited to 'Makefile') diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7d655ff --- /dev/null +++ b/Makefile @@ -0,0 +1,148 @@ +# Bitflash — top-level build +# +# make linux build Bitflash-*-x86_64.AppImage +# make windows build Bitflash-*-windows.zip (from MSYS2 UCRT64) +# make clean remove build artifacts + +ROOT := $(shell pwd) +NPROC := $(shell nproc 2>/dev/null || echo 2) +SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") +VERSION := 1.1.0 + +# ---- Linux ---------------------------------------------------------------- + +linux: deps-linux + $(MAKE) -C src -f Makefile -j$(NPROC) + strip src/bitflash + $(MAKE) -f Makefile appimage + +deps-linux: deps-apt deps-secp256k1 deps-randomx + +deps-apt: + @if command -v apt-get >/dev/null 2>&1; then \ + $(SUDO) apt-get install -y build-essential cmake git pkg-config autoconf \ + libtool libssl-dev libdb5.3++-dev libsodium-dev nlohmann-json3-dev \ + libboost-system-dev libglfw3-dev libgl-dev; \ + else \ + echo "Not an apt system — install: g++ cmake git autoconf libtool"; \ + echo " libssl libdb++ libsodium nlohmann-json boost glfw3 opengl"; \ + fi + +deps-secp256k1: + @if [ ! -f /usr/local/lib/libsecp256k1.a ]; then \ + echo "==> building libsecp256k1"; \ + rm -rf $(ROOT)/secp256k1-build; \ + git clone --depth 1 https://github.com/bitcoin-core/secp256k1 $(ROOT)/secp256k1-build; \ + cd $(ROOT)/secp256k1-build && ./autogen.sh && \ + ./configure --enable-module-schnorrsig --enable-module-extrakeys \ + --disable-shared --with-pic --disable-benchmark --disable-tests && \ + make -j$(NPROC) && $(SUDO) make install && $(SUDO) ldconfig; \ + echo "==> libsecp256k1 done"; \ + else \ + echo "==> libsecp256k1 already installed"; \ + fi + +deps-randomx: + @if [ ! -f $(HOME)/RandomX/build/librandomx.a ]; then \ + echo "==> building RandomX"; \ + rm -rf $(HOME)/RandomX; \ + git clone --depth 1 https://github.com/tevador/RandomX $(HOME)/RandomX; \ + mkdir -p $(HOME)/RandomX/build; \ + cd $(HOME)/RandomX/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \ + make -j$(NPROC) randomx; \ + echo "==> RandomX done"; \ + else \ + echo "==> RandomX already built"; \ + fi + +appimage: src/bitflash + @echo "==> building AppImage" + @if [ ! -x /tmp/appimagetool ]; then \ + wget -q "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" \ + -O /tmp/appimagetool && chmod +x /tmp/appimagetool; \ + fi + @rm -rf /tmp/bitflash.AppDir + @mkdir -p /tmp/bitflash.AppDir/usr/bin \ + /tmp/bitflash.AppDir/usr/lib \ + /tmp/bitflash.AppDir/usr/share/applications \ + /tmp/bitflash.AppDir/usr/share/icons/hicolor/256x256/apps + @cp src/bitflash /tmp/bitflash.AppDir/usr/bin/bitflash + @printf '#!/bin/sh\nHERE="$$(dirname "$$(readlink -f "$$0")")"\nexport LD_LIBRARY_PATH="$$HERE/usr/lib:$$LD_LIBRARY_PATH"\nexec "$$HERE/usr/bin/bitflash" "$$@"\n' \ + > /tmp/bitflash.AppDir/AppRun && chmod +x /tmp/bitflash.AppDir/AppRun + @printf '[Desktop Entry]\nName=Bitflash\nExec=bitflash\nIcon=bitflash\nType=Application\nCategories=Finance;\n' \ + > /tmp/bitflash.AppDir/bitflash.desktop + @cp /tmp/bitflash.AppDir/bitflash.desktop \ + /tmp/bitflash.AppDir/usr/share/applications/ + @python3 -c "\ +from PIL import Image; \ +ico = Image.open('src/rc/bitcoin.ico'); \ +img = ico.convert('RGBA'); \ +img.save('/tmp/bitflash.AppDir/bitflash.png'); \ +import shutil; shutil.copy('/tmp/bitflash.AppDir/bitflash.png', \ +'/tmp/bitflash.AppDir/usr/share/icons/hicolor/256x256/apps/bitflash.png')" + @for lib in libsodium.so.23 libdb_cxx-5.3.so libglfw.so.3; do \ + path=$$(ldconfig -p | grep " $$lib " | awk '{print $$NF}' | head -1); \ + [ -z "$$path" ] && path=$$(find /usr/lib /lib -name "$$lib" 2>/dev/null | head -1); \ + [ -n "$$path" ] && cp -L "$$path" /tmp/bitflash.AppDir/usr/lib/ && echo " bundled $$lib" || echo " missing $$lib"; \ + done + @ARCH=x86_64 /tmp/appimagetool --no-appstream /tmp/bitflash.AppDir \ + $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage 2>&1 | grep -E "^Built|^Error" || true + @echo "Built: Bitflash-$(VERSION)-x86_64.AppImage" + +# ---- Windows (MSYS2 UCRT64) ----------------------------------------------- + +deps-windows: + pacman -S --noconfirm --needed \ + mingw-w64-ucrt-x86_64-gcc \ + mingw-w64-ucrt-x86_64-make \ + mingw-w64-ucrt-x86_64-glfw \ + mingw-w64-ucrt-x86_64-openssl \ + mingw-w64-ucrt-x86_64-db \ + mingw-w64-ucrt-x86_64-libsodium \ + mingw-w64-ucrt-x86_64-nlohmann-json \ + mingw-w64-ucrt-x86_64-boost \ + mingw-w64-ucrt-x86_64-cmake \ + autoconf automake libtool + @if [ ! -f deps/lib/libsecp256k1.a ]; then \ + rm -rf secp256k1-build; \ + git clone --depth 1 https://github.com/bitcoin-core/secp256k1 secp256k1-build; \ + cd secp256k1-build && ./autogen.sh && \ + ./configure --prefix=$(ROOT)/deps \ + --enable-module-schnorrsig --enable-module-extrakeys \ + --disable-shared --with-pic --disable-benchmark --disable-tests && \ + make install; \ + echo "==> secp256k1 done"; \ + else \ + echo "==> secp256k1 already built"; \ + fi + @if [ ! -f RandomX/build/librandomx.a ]; then \ + rm -rf RandomX; \ + git clone --depth 1 https://github.com/tevador/RandomX; \ + mkdir -p RandomX/build; \ + cd RandomX/build && cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release && \ + make randomx; \ + echo "==> RandomX done"; \ + else \ + echo "==> RandomX already built"; \ + fi + +windows: deps-windows + cd src && make -f makefile.mingw + @rm -rf Bitflash-$(VERSION)-windows + @mkdir -p Bitflash-$(VERSION)-windows + @cp src/bitflash.exe Bitflash-$(VERSION)-windows/Bitflash.exe + @ldd src/bitflash.exe | grep ucrt64 | awk '{print $$3}' | \ + xargs -I{} cp {} Bitflash-$(VERSION)-windows/ 2>/dev/null || true + @zip -r Bitflash-$(VERSION)-windows.zip Bitflash-$(VERSION)-windows/ + @echo "Built: Bitflash-$(VERSION)-windows.zip" + +# ---- Clean ---------------------------------------------------------------- + +clean: + $(MAKE) -C src -f Makefile clean 2>/dev/null || true + cd src && make -f makefile.mingw clean 2>/dev/null || true + rm -f Bitflash-*.AppImage Bitflash-*.zip + rm -rf Bitflash-*-windows + +.PHONY: linux windows clean appimage \ + deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx -- cgit v1.2.3 From 8767500e5de2deb7cd9d21757a45ca41b9f427b7 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Tue, 28 Jul 2026 13:14:27 -0300 Subject: Release plumbing: bump to 1.2.0, add python3-pil to Linux deps (#10) The AppImage step converts src/rc/bitcoin.ico with PIL, but python3-pil was never in deps-apt, so 'make linux' failed at packaging on a clean Debian install -- the AppImage the README points Linux users at could not actually be produced by following the documented steps. Version bump only renames the produced artefacts; no rebuild needed. --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 7d655ff..b334a7a 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.1.0 +VERSION := 1.2.0 # ---- Linux ---------------------------------------------------------------- @@ -22,10 +22,10 @@ deps-apt: @if command -v apt-get >/dev/null 2>&1; then \ $(SUDO) apt-get install -y build-essential cmake git pkg-config autoconf \ libtool libssl-dev libdb5.3++-dev libsodium-dev nlohmann-json3-dev \ - libboost-system-dev libglfw3-dev libgl-dev; \ + libboost-system-dev libglfw3-dev libgl-dev python3-pil; \ else \ echo "Not an apt system — install: g++ cmake git autoconf libtool"; \ - echo " libssl libdb++ libsodium nlohmann-json boost glfw3 opengl"; \ + echo " libssl libdb++ libsodium nlohmann-json boost glfw3 opengl python3-pil"; \ fi deps-secp256k1: -- cgit v1.2.3 From 9eb1b6a3633cae6e644ea9f43e34e890c691f937 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Tue, 28 Jul 2026 14:00:54 -0300 Subject: Bump to 1.2.1 for the consensus security release (#14) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index b334a7a..1ff36ce 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.0 +VERSION := 1.2.1 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From ba2de82b76aeeabe1c45877e02b0e8fe5b59bed3 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Tue, 28 Jul 2026 15:33:34 -0300 Subject: Bump to 1.2.2 for the hardening release (#24) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 1ff36ce..6c0efc6 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.1 +VERSION := 1.2.2 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From 82e47c97375c24980051451a613fbdd433d6c333 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Wed, 29 Jul 2026 14:18:44 -0300 Subject: Bump to 1.2.3 for the connectivity release (#33) Everything since 1.2.2 is about nodes being able to find and reach each other, which is the problem this project actually had: #30 rendezvous registration and waiting split apart. Registering used to block until somebody dialled, so a node could not advertise a meeting node until it had already been reached at one. This is the root cause of the flaky connectivity, not dead relays or stale descriptors. #26 a node no longer advertises a rendezvous it is not registered at #25 .btf peers that answered are remembered and dialled first (36.3s -> 2.1s) #32 peers exchange signed descriptors, so discovery survives a relay outage #29 debug.log stopped dropping lines under concurrency #28 /port, so two nodes can share a machine --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 6c0efc6..9cfef2f 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.2 +VERSION := 1.2.3 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From c404e1c7f5d3f04d07e7e5b35a7a8ffcc998d855 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Wed, 29 Jul 2026 16:33:02 -0300 Subject: build: headless Linux node that does not need libGL (#37) The GUI build requires libGL at load time even when started with -nogui. The dynamic loader resolves every dependency before main() runs, so the flag arrives far too late -- on a clean server the binary dies with error while loading shared libraries: libGL.so.1: cannot open shared object file and nothing suggests it would otherwise have worked. A server is where a node most naturally lives, so this is the deployment that mattered most and the one that failed. The AppImage additionally needs FUSE, which minimal servers lack. Bundling libGL into the AppImage would be the wrong fix: GL has to come from the host's driver stack, and shipping our own breaks machines that have a real GPU. So: a second binary, built from the same node objects without ImGui, GLFW or OpenGL. `make linux-node` produces bitflash-node--x86_64, 2.5 MB stripped, with no graphics or FUSE dependency at all. `make linux` now builds it alongside the AppImage. Anyone wanting a window keeps using the AppImage. Two small moves were needed. MainFrameRepaint is called from main.cpp and net.cpp but defined in gui.cpp, so headless.cpp provides an empty one rather than putting ifdefs at six call sites. DateTimeStr also lived in gui.cpp while main.cpp logs block times with it -- nothing about formatting a date is GUI work, so it moved to util.cpp and both builds share one definition. Verified on Debian 13: ldd bitflash-node | grep -iE 'libGL|glfw|X11' -> nothing ldd bitflash | grep -iE 'libGL|glfw' -> libglfw.so.3, libGL.so.1, libGLdispatch.so.0 and at runtime, from an empty datadir: btfseed: reached ygffz37...btf via 90.156.222.107:8434 rendezvous: registered at 90.156.222.107:8434, waiting for a dial self-resolve OK (meeting_node=90.156.222.107:8434) btfpeers: kept 15 of 15 descriptor(s) first block at ~30s, 3182 blocks accepted, synced to the tip The GUI builds on Linux and Windows were rebuilt and are unaffected. --- Makefile | 12 ++++++++++++ src/Makefile | 32 +++++++++++++++++++++++++++++++- src/gui.cpp | 10 ++-------- src/headless.cpp | 20 ++++++++++++++++++++ src/main_gui.cpp | 13 +++++++++++++ src/util.cpp | 12 ++++++++++++ 6 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 src/headless.cpp (limited to 'Makefile') diff --git a/Makefile b/Makefile index 9cfef2f..b5bfa9a 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,18 @@ linux: deps-linux $(MAKE) -C src -f Makefile -j$(NPROC) strip src/bitflash $(MAKE) -f Makefile appimage + $(MAKE) -f Makefile linux-node + +# Headless node, no ImGui/GLFW/OpenGL. The GUI build needs libGL present at load +# time even when started with -nogui -- the dynamic loader resolves everything +# before main() runs, so the flag comes far too late. On a clean server, which is +# where a node most naturally lives, that is a hard failure. This binary has no +# such dependency and needs no FUSE either, so it drops onto a VPS and runs. +linux-node: deps-linux + $(MAKE) -C src -f Makefile bitflash-node -j$(NPROC) + strip src/bitflash-node + cp src/bitflash-node bitflash-node-$(VERSION)-x86_64 + @echo "Built: bitflash-node-$(VERSION)-x86_64" deps-linux: deps-apt deps-secp256k1 deps-randomx diff --git a/src/Makefile b/src/Makefile index c0b6e1d..9846d8e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -71,5 +71,35 @@ bitflash: $(IMGUI_OBJS) $(NODE_OBJS) $(GUI_OBJS) $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) @echo "Built: bitflash" +# ---- headless node --------------------------------------------------------- +# +# Same node, built without ImGui, GLFW or OpenGL. Linking the GUI made the +# binary require libGL at load time even when started with -nogui, because the +# dynamic loader resolves everything before main() runs -- so on a clean server, +# which is where a node most naturally lives, it failed to start with an error +# about shared libraries and no hint that it would otherwise work. +# +# Objects go to obj-node/ because main_gui.cpp is compiled twice, with and +# without -DBITFLASH_NO_GUI, and the two must not overwrite each other. + +NODE_LIBS = -L$(SECP_LIB) -lsecp256k1 \ + -L$(RANDOMX_DIR)/build -lrandomx \ + -lsodium -lssl -lcrypto -ldb_cxx -lpthread + +NODE_ONLY_OBJS = $(patsubst obj/%,obj-node/%,$(NODE_OBJS)) \ + obj-node/main_gui.o obj-node/headless.o + +obj-node/%.o: %.cpp $(HEADERS) + @mkdir -p obj-node + $(CXX) -c $(CXXFLAGS) -DBITFLASH_NO_GUI -o $@ $< + +obj-node/sha.o: sha.cpp sha.h + @mkdir -p obj-node + $(CXX) -c $(CXXFLAGS) -DBITFLASH_NO_GUI -O3 -o $@ $< + +bitflash-node: $(NODE_ONLY_OBJS) + $(CXX) $(CXXFLAGS) -o $@ $^ $(NODE_LIBS) + @echo "Built: bitflash-node (headless, no libGL needed)" + clean: - rm -rf obj bitflash + rm -rf obj obj-node bitflash bitflash-node diff --git a/src/gui.cpp b/src/gui.cpp index a1a0698..fc6f1e1 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -171,14 +171,8 @@ static void RefreshWallet() void MainFrameRepaint() { g_needRefresh = true; } -string DateTimeStr(int64 nTime) -{ - time_t t = (time_t)nTime; - struct tm* p = localtime(&t); - if (!p) return ""; - char buf[32]; strftime(buf, sizeof(buf), "%m/%d/%y %H:%M", p); - return buf; -} +// DateTimeStr moved to util.cpp: main.cpp logs block times with it, so it is +// needed by builds that have no GUI at all. // --------------------------------------------------------------------------- // Status bar -- separate fullscreen-width overlay pinned to bottom edge. diff --git a/src/headless.cpp b/src/headless.cpp new file mode 100644 index 0000000..3372936 --- /dev/null +++ b/src/headless.cpp @@ -0,0 +1,20 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. +// +// Stand-ins for the handful of symbols the node core expects the GUI to +// provide, so a headless binary can be linked without ImGui, GLFW or OpenGL. +// +// This exists because linking the GUI made the node need libGL at load time +// even when started with -nogui: the dynamic loader resolves everything before +// main() runs, so the flag came far too late. On a clean server -- which is +// where a node most naturally lives -- that is a hard failure with an error +// message about shared libraries and no hint that the program would otherwise +// have worked fine. + +#include "headers_core.h" + +// The GUI uses this to mark itself dirty. With no window to repaint there is +// nothing to do, and the call sites in main.cpp and net.cpp stay unchanged. +void MainFrameRepaint() +{ +} diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 9f7e34e..99e63d4 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -5,7 +5,11 @@ #include #endif +// BITFLASH_NO_GUI builds the same entry point without ImGui, GLFW or OpenGL, +// so the binary does not need libGL present just to start. See headless.cpp. +#ifndef BITFLASH_NO_GUI int RunGUI(int argc, char* argv[]); +#endif // Global definitions (were in ui.cpp, now here) map mapAddressBook; @@ -186,8 +190,13 @@ int main(int argc, char* argv[]) if (_beginthread(ThreadBitcoinMiner, 0, NULL) == (uintptr_t)-1) printf("Error: _beginthread(ThreadBitcoinMiner) failed\n"); +#ifdef BITFLASH_NO_GUI + // Nothing else this binary can do; /nogui is accepted and redundant. + bool fHeadless = true; +#else bool fHeadless = arg(argc,argv,"/nogui") || arg(argc,argv,"-nogui") || arg(argc,argv,"/daemon") || arg(argc,argv,"-daemon"); +#endif if (fHeadless) { #ifndef _WIN32 @@ -200,8 +209,12 @@ int main(int argc, char* argv[]) return 0; } +#ifdef BITFLASH_NO_GUI + return 0; // unreachable: fHeadless is always true in this build +#else int ret = RunGUI(argc, argv); fShutdown = true; StopNode(); return ret; +#endif } diff --git a/src/util.cpp b/src/util.cpp index 68bd18e..e4e314f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -490,3 +490,15 @@ void AddTimeData(unsigned int ip, int64 nTime) printf("| nTimeOffset = %+lld (%+lld minutes)\n", nTimeOffset, nTimeOffset/60); } } + +// Formats a block or transaction timestamp for logs and for the wallet view. +// It lived in gui.cpp, but main.cpp logs block times with it, so a headless +// build needed it too -- and nothing about formatting a date is GUI work. +string DateTimeStr(int64 nTime) +{ + time_t t = (time_t)nTime; + struct tm* p = localtime(&t); + if (!p) return ""; + char buf[32]; strftime(buf, sizeof(buf), "%m/%d/%y %H:%M", p); + return buf; +} -- cgit v1.2.3 From a3f9d87ef3c610f4158b64e44ac6b074d386b06a Mon Sep 17 00:00:00 2001 From: Bitflash Date: Wed, 29 Jul 2026 17:46:27 -0300 Subject: Bump to 1.2.4 (#39) Seeds (#36), headless node (#37), README (#35), wallet crash fix (#38). --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index b5bfa9a..e21122a 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.3 +VERSION := 1.2.4 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From de884e493145bd5cbd1d7a049968edcd110391af Mon Sep 17 00:00:00 2001 From: Bitflash Date: Thu, 30 Jul 2026 10:45:00 -0300 Subject: Bump to 1.2.5 (#45) Headless mining fix (#42), ARM64 build (#41), format-string checking (#44), gitignore for key material (#43). #42 is the reason this release exists: -gen has mined nothing on headless nodes since v1.2.0. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index e21122a..977a392 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.4 +VERSION := 1.2.5 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From daac46893448e49a21244d9646acf0ec47518537 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Thu, 30 Jul 2026 11:39:40 -0300 Subject: Bump to 1.2.6 (#48) Wallet backup and clean shutdown (#46). Two reasons not to sit on this: every Linux node aborts on the way out instead of releasing wallet.dat, and until a node has shut down cleanly once, the wallet it wrote cannot be moved anywhere else. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 977a392..0824100 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.5 +VERSION := 1.2.6 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From 88a1e9973e34c972e965fe5dd16cd1f891885bba Mon Sep 17 00:00:00 2001 From: Bitflash Date: Thu, 30 Jul 2026 14:18:19 -0300 Subject: Bump to 1.2.7 (#53) Rendezvous no longer waits forever for a dial (#51), keys can be exported and imported as text (#49), and mining uses every core instead of one (#52). #51 is the reason not to sit on this: without it a node goes silently deaf after a while and only a restart brings it back. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0824100..0e23337 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.6 +VERSION := 1.2.7 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From 7243bbead29d68c9f8ae9a022669b02179e352e2 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Fri, 31 Jul 2026 08:54:19 -0300 Subject: Bump to 1.2.8 (#63) Six changes since 1.2.7, and the reason not to sit on this is #58: coinbase transactions were not unique, two of them overwrote older ones on the main chain, and 100 BTF stopped being reachable. Nothing in how they were built had changed since, so it could happen again at any time. The height now goes into the coinbase on both paths that build one (#59, #60), which makes a repeat impossible without any coordination. Also in: a node now notices a peer it can no longer hear and stays audible to peers that check the same way (#55); it announces its height in the handshake and says out loud when it falls behind the network (#56); script evaluation has ceilings on operation count and stack depth (#57); the tail of the chain is verified at startup and a bad tip is backed out of instead of being mined on (#61); and the wallet now believes the chain about what it has already spent, which is what a restored backup gets wrong (#62). --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0e23337..fa603d5 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.7 +VERSION := 1.2.8 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From cca4e0c38595653846d9907650870df8c0768d77 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Fri, 31 Jul 2026 09:43:31 -0300 Subject: Bump to 1.2.9 (#66) relay.nostr.band went down and stayed down. Every node running 1.2.8 or earlier spends ten seconds of every discovery pass waiting for it and writes an error line each time -- the seed logged 2029 of them. #64 replaces it with a relay that answers and backs off from any relay that stops answering, so the next one to go down costs nothing. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index fa603d5..dd66261 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.8 +VERSION := 1.2.9 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From 795e51612bd5b17dbbf8f0cbea64ee4c874b5a33 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Fri, 31 Jul 2026 16:38:19 -0300 Subject: Bump to 1.2.10 (#77) 1.2.9 shipped before the last seven merges landed, and one of them is holding two live nodes hostage. Measured on a 32-core node running 1.2.9 today: 65,134 MB committed, which is 30 RandomX datasets at 2,142 MB each -- one per miner thread, for a node that advertises 2 GB. A 4-core node on the same build sits at 6,568 MB, three datasets. #68 allocates the dataset once and closes the window where a thread could mine against one that was not finished being filled. The rest of the release: - #67 orphans no longer stack above earned blocks in the GUI list - #69 no submitting a solution for a parent that is no longer the tip - #70 a ceiling on orphan blocks, and getblocks stops repeating itself - #71 Berkeley DB cursors get closed instead of left to the handle - #73 bounds on what a peer can make the node allocate - #74 the recipient no longer collects the fee when a transaction retries --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index dd66261..970114d 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.9 +VERSION := 1.2.10 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From 64b9507846846e468ebba7e00fb59971edceca3b Mon Sep 17 00:00:00 2001 From: mtg0001 <106211915+mtg0001@users.noreply.github.com> Date: Sat, 1 Aug 2026 12:23:28 -0300 Subject: Add BIP39 and BIP32 foundation tests (#83) Co-authored-by: Gilcimar Duarte --- Makefile | 6 +- src/Makefile | 8 +- src/bip32.cpp | 366 +++++++++ src/bip32.h | 53 ++ src/bip39_english.h | 2062 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/makefile.mingw | 9 +- src/test_bip32.cpp | 130 ++++ 7 files changed, 2631 insertions(+), 3 deletions(-) create mode 100644 src/bip32.cpp create mode 100644 src/bip32.h create mode 100644 src/bip39_english.h create mode 100644 src/test_bip32.cpp (limited to 'Makefile') diff --git a/Makefile b/Makefile index 970114d..d436885 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ # # make linux build Bitflash-*-x86_64.AppImage # make windows build Bitflash-*-windows.zip (from MSYS2 UCRT64) +# make tests build and run standalone unit tests # make clean remove build artifacts ROOT := $(shell pwd) @@ -156,5 +157,8 @@ clean: rm -f Bitflash-*.AppImage Bitflash-*.zip rm -rf Bitflash-*-windows +tests: + $(MAKE) -C src -f Makefile tests + .PHONY: linux windows clean appimage \ - deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx + tests deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx diff --git a/src/Makefile b/src/Makefile index f0c6706..4e104c0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -121,4 +121,10 @@ bitflash-node: $(NODE_ONLY_OBJS) @echo "Built: bitflash-node (headless, no libGL needed)" clean: - rm -rf obj obj-node bitflash bitflash-node + rm -rf obj obj-node bitflash bitflash-node test_bip32 + +test_bip32: test_bip32.cpp bip32.cpp bip32.h bip39_english.h + $(CXX) $(CXXFLAGS) -o $@ test_bip32.cpp bip32.cpp -lssl -lcrypto + +tests: test_bip32 + ./test_bip32 diff --git a/src/bip32.cpp b/src/bip32.cpp new file mode 100644 index 0000000..6423974 --- /dev/null +++ b/src/bip32.cpp @@ -0,0 +1,366 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. + +#include "bip32.h" +#include "bip39_english.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace bitflash +{ + +static bool IsSupportedEntropySize(size_t n) +{ + return n == 16 || n == 20 || n == 24 || n == 28 || n == 32; +} + +static bool GetBit(const unsigned char* data, size_t bit) +{ + return (data[bit / 8] >> (7 - (bit % 8))) & 1; +} + +static void AppendBits(std::vector& out, const unsigned char* data, + size_t nBits) +{ + for (size_t i = 0; i < nBits; i++) + out.push_back(GetBit(data, i)); +} + +static std::string NormalizeMnemonic(const std::string& in) +{ + std::string out; + bool inSpace = true; + for (unsigned char c : in) + { + if (std::isspace(c)) + { + if (!inSpace) + out.push_back(' '); + inSpace = true; + } + else + { + out.push_back((char)std::tolower(c)); + inSpace = false; + } + } + if (!out.empty() && out.back() == ' ') + out.pop_back(); + return out; +} + +static std::vector SplitWords(const std::string& phrase) +{ + std::vector words; + std::istringstream in(phrase); + std::string word; + while (in >> word) + words.push_back(word); + return words; +} + +static const std::map& WordIndex() +{ + static std::map m; + if (m.empty()) + { + for (int i = 0; i < 2048; i++) + m[BIP39_ENGLISH_WORDS[i]] = i; + } + return m; +} + +static bool IsValidPrivateKey(const std::vector& key) +{ + if (key.size() != 32) + return false; + bool fNonZero = false; + for (unsigned char c : key) + fNonZero = fNonZero || c != 0; + if (!fNonZero) + return false; + + bool ok = false; + BIGNUM* bn = BN_bin2bn(&key[0], 32, NULL); + BIGNUM* order = BN_new(); + EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp256k1); + if (bn && order && group && EC_GROUP_get_order(group, order, NULL)) + ok = BN_cmp(bn, order) < 0; + BN_free(bn); + BN_free(order); + EC_GROUP_free(group); + return ok; +} + +static bool HmacSha512(const unsigned char* key, int keyLen, + const unsigned char* data, size_t dataLen, + unsigned char out[64]) +{ + unsigned int len = 64; + return HMAC(EVP_sha512(), key, keyLen, data, dataLen, out, &len) != NULL && + len == 64; +} + +bool BIP39EntropyToMnemonic(const std::vector& entropy, + std::string& mnemonicOut, + std::string& errorOut) +{ + mnemonicOut.clear(); + errorOut.clear(); + if (!IsSupportedEntropySize(entropy.size())) + { + errorOut = "entropy must be 128, 160, 192, 224, or 256 bits"; + return false; + } + + unsigned char checksum[SHA256_DIGEST_LENGTH]; + SHA256(&entropy[0], entropy.size(), checksum); + + const size_t entropyBits = entropy.size() * 8; + const size_t checksumBits = entropyBits / 32; + + std::vector bits; + bits.reserve(entropyBits + checksumBits); + AppendBits(bits, &entropy[0], entropyBits); + AppendBits(bits, checksum, checksumBits); + + const size_t words = bits.size() / 11; + for (size_t i = 0; i < words; i++) + { + int idx = 0; + for (int j = 0; j < 11; j++) + idx = (idx << 1) | (bits[i * 11 + j] ? 1 : 0); + if (i != 0) + mnemonicOut += " "; + mnemonicOut += BIP39_ENGLISH_WORDS[idx]; + } + return true; +} + +bool BIP39GenerateMnemonic(std::string& mnemonicOut, + std::string& errorOut, + unsigned int entropyBytes) +{ + mnemonicOut.clear(); + errorOut.clear(); + if (!IsSupportedEntropySize(entropyBytes)) + { + errorOut = "entropy must be 16, 20, 24, 28, or 32 bytes"; + return false; + } + + std::vector entropy(entropyBytes); + if (RAND_bytes(&entropy[0], entropy.size()) != 1) + { + errorOut = "RAND_bytes failed"; + return false; + } + bool ok = BIP39EntropyToMnemonic(entropy, mnemonicOut, errorOut); + OPENSSL_cleanse(&entropy[0], entropy.size()); + return ok; +} + +bool BIP39ValidateMnemonic(const std::string& mnemonic, + std::string& normalizedOut, + std::string& errorOut) +{ + normalizedOut = NormalizeMnemonic(mnemonic); + errorOut.clear(); + std::vector words = SplitWords(normalizedOut); + const size_t nWords = words.size(); + if (nWords != 12 && nWords != 15 && nWords != 18 && nWords != 21 && nWords != 24) + { + errorOut = "mnemonic must contain 12, 15, 18, 21, or 24 words"; + return false; + } + + const std::map& index = WordIndex(); + std::vector bits; + bits.reserve(nWords * 11); + for (const std::string& word : words) + { + std::map::const_iterator mi = index.find(word); + if (mi == index.end()) + { + errorOut = "mnemonic contains a word outside the BIP39 English list"; + return false; + } + int value = mi->second; + for (int i = 10; i >= 0; i--) + bits.push_back(((value >> i) & 1) != 0); + } + + const size_t totalBits = bits.size(); + const size_t entropyBits = totalBits * 32 / 33; + const size_t checksumBits = totalBits - entropyBits; + std::vector entropy(entropyBits / 8, 0); + for (size_t i = 0; i < entropyBits; i++) + if (bits[i]) + entropy[i / 8] |= (unsigned char)(1 << (7 - (i % 8))); + + unsigned char checksum[SHA256_DIGEST_LENGTH]; + SHA256(&entropy[0], entropy.size(), checksum); + for (size_t i = 0; i < checksumBits; i++) + { + if (bits[entropyBits + i] != GetBit(checksum, i)) + { + errorOut = "mnemonic checksum failed"; + return false; + } + } + return true; +} + +bool BIP39MnemonicToSeed(const std::string& mnemonic, + const std::string& passphrase, + std::vector& seedOut, + std::string& errorOut) +{ + seedOut.assign(64, 0); + std::string normalized; + if (!BIP39ValidateMnemonic(mnemonic, normalized, errorOut)) + { + seedOut.clear(); + return false; + } + + const std::string salt = "mnemonic" + passphrase; + if (!PKCS5_PBKDF2_HMAC(normalized.c_str(), normalized.size(), + (const unsigned char*)salt.data(), salt.size(), + 2048, EVP_sha512(), 64, &seedOut[0])) + { + seedOut.clear(); + errorOut = "PBKDF2-HMAC-SHA512 failed"; + return false; + } + return true; +} + +bool BIP32MasterFromSeed(const std::vector& seed, + BIP32PrivateNode& nodeOut, + std::string& errorOut) +{ + nodeOut.privateKey.clear(); + nodeOut.chainCode.clear(); + errorOut.clear(); + if (seed.size() < 16 || seed.size() > 64) + { + errorOut = "BIP32 seed must be between 128 and 512 bits"; + return false; + } + + unsigned char I[64]; + static const unsigned char key[] = "Bitcoin seed"; + if (!HmacSha512(key, sizeof(key) - 1, &seed[0], seed.size(), I)) + { + errorOut = "HMAC-SHA512 failed"; + return false; + } + + nodeOut.privateKey.assign(I, I + 32); + nodeOut.chainCode.assign(I + 32, I + 64); + OPENSSL_cleanse(I, sizeof(I)); + + if (!IsValidPrivateKey(nodeOut.privateKey)) + { + nodeOut.privateKey.clear(); + nodeOut.chainCode.clear(); + errorOut = "BIP32 master key is invalid"; + return false; + } + return true; +} + +bool BIP32DeriveHardenedChild(const BIP32PrivateNode& parent, + unsigned int childIndex, + BIP32PrivateNode& childOut, + std::string& errorOut) +{ + childOut.privateKey.clear(); + childOut.chainCode.clear(); + errorOut.clear(); + if (!IsValidPrivateKey(parent.privateKey) || parent.chainCode.size() != 32) + { + errorOut = "parent private key or chain code is invalid"; + return false; + } + if (childIndex >= 0x80000000U) + { + errorOut = "child index must be non-hardened; hardening is applied here"; + return false; + } + + const unsigned int hardened = childIndex | 0x80000000U; + unsigned char data[37]; + data[0] = 0x00; + memcpy(data + 1, &parent.privateKey[0], 32); + data[33] = (unsigned char)((hardened >> 24) & 0xff); + data[34] = (unsigned char)((hardened >> 16) & 0xff); + data[35] = (unsigned char)((hardened >> 8) & 0xff); + data[36] = (unsigned char)(hardened & 0xff); + + unsigned char I[64]; + if (!HmacSha512(&parent.chainCode[0], 32, data, sizeof(data), I)) + { + OPENSSL_cleanse(data, sizeof(data)); + errorOut = "HMAC-SHA512 failed"; + return false; + } + OPENSSL_cleanse(data, sizeof(data)); + + std::vector IL(I, I + 32); + childOut.chainCode.assign(I + 32, I + 64); + OPENSSL_cleanse(I, sizeof(I)); + + BIGNUM* bnIL = BN_bin2bn(&IL[0], 32, NULL); + BIGNUM* bnParent = BN_bin2bn(&parent.privateKey[0], 32, NULL); + BIGNUM* bnOrder = BN_new(); + BIGNUM* bnChild = BN_new(); + BN_CTX* ctx = BN_CTX_new(); + EC_GROUP* group = EC_GROUP_new_by_curve_name(NID_secp256k1); + + bool ok = false; + if (bnIL && bnParent && bnOrder && bnChild && ctx && group && + EC_GROUP_get_order(group, bnOrder, NULL) && + BN_cmp(bnIL, bnOrder) < 0 && + BN_mod_add(bnChild, bnIL, bnParent, bnOrder, ctx) && + !BN_is_zero(bnChild)) + { + childOut.privateKey.assign(32, 0); + int n = BN_num_bytes(bnChild); + BN_bn2bin(bnChild, &childOut.privateKey[32 - n]); + ok = true; + } + + BN_free(bnIL); + BN_free(bnParent); + BN_free(bnOrder); + BN_free(bnChild); + BN_CTX_free(ctx); + EC_GROUP_free(group); + OPENSSL_cleanse(&IL[0], IL.size()); + + if (!ok) + { + childOut.privateKey.clear(); + childOut.chainCode.clear(); + errorOut = "BIP32 child derivation produced an invalid key"; + return false; + } + return true; +} + +} // namespace bitflash diff --git a/src/bip32.h b/src/bip32.h new file mode 100644 index 0000000..a029444 --- /dev/null +++ b/src/bip32.h @@ -0,0 +1,53 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. +// +// BIP39/BIP32 primitives for deterministic wallet work. +// +// This module is deliberately independent from wallet.dat and GUI code. It is +// the auditable foundation: mnemonic generation/validation, seed derivation, +// and hardened private child derivation over secp256k1. + +#ifndef BITFLASH_BIP32_H +#define BITFLASH_BIP32_H + +#include +#include + +namespace bitflash +{ + +struct BIP32PrivateNode +{ + std::vector privateKey; // 32-byte scalar + std::vector chainCode; // 32 bytes +}; + +bool BIP39EntropyToMnemonic(const std::vector& entropy, + std::string& mnemonicOut, + std::string& errorOut); + +bool BIP39GenerateMnemonic(std::string& mnemonicOut, + std::string& errorOut, + unsigned int entropyBytes = 16); + +bool BIP39ValidateMnemonic(const std::string& mnemonic, + std::string& normalizedOut, + std::string& errorOut); + +bool BIP39MnemonicToSeed(const std::string& mnemonic, + const std::string& passphrase, + std::vector& seedOut, + std::string& errorOut); + +bool BIP32MasterFromSeed(const std::vector& seed, + BIP32PrivateNode& nodeOut, + std::string& errorOut); + +bool BIP32DeriveHardenedChild(const BIP32PrivateNode& parent, + unsigned int childIndex, + BIP32PrivateNode& childOut, + std::string& errorOut); + +} // namespace bitflash + +#endif diff --git a/src/bip39_english.h b/src/bip39_english.h new file mode 100644 index 0000000..04b4ed2 --- /dev/null +++ b/src/bip39_english.h @@ -0,0 +1,2062 @@ +// BIP39 English Wordlist + +#ifndef BITFLASH_BIP39_ENGLISH_H +#define BITFLASH_BIP39_ENGLISH_H + +namespace bitflash +{ + +static const char* BIP39_ENGLISH_WORDS[2048] = { + "abandon", + "ability", + "able", + "about", + "above", + "absent", + "absorb", + "abstract", + "absurd", + "abuse", + "access", + "accident", + "account", + "accuse", + "achieve", + "acid", + "acoustic", + "acquire", + "across", + "act", + "action", + "actor", + "actress", + "actual", + "adapt", + "add", + "addict", + "address", + "adjust", + "admit", + "adult", + "advance", + "advice", + "aerobic", + "affair", + "afford", + "afraid", + "again", + "age", + "agent", + "agree", + "ahead", + "aim", + "air", + "airport", + "aisle", + "alarm", + "album", + "alcohol", + "alert", + "alien", + "all", + "alley", + "allow", + "almost", + "alone", + "alpha", + "already", + "also", + "alter", + "always", + "amateur", + "amazing", + "among", + "amount", + "amused", + "analyst", + "anchor", + "ancient", + "anger", + "angle", + "angry", + "animal", + "ankle", + "announce", + "annual", + "another", + "answer", + "antenna", + "antique", + "anxiety", + "any", + "apart", + "apology", + "appear", + "apple", + "approve", + "april", + "arch", + "arctic", + "area", + "arena", + "argue", + "arm", + "armed", + "armor", + "army", + "around", + "arrange", + "arrest", + "arrive", + "arrow", + "art", + "artefact", + "artist", + "artwork", + "ask", + "aspect", + "assault", + "asset", + "assist", + "assume", + "asthma", + "athlete", + "atom", + "attack", + "attend", + "attitude", + "attract", + "auction", + "audit", + "august", + "aunt", + "author", + "auto", + "autumn", + "average", + "avocado", + "avoid", + "awake", + "aware", + "away", + "awesome", + "awful", + "awkward", + "axis", + "baby", + "bachelor", + "bacon", + "badge", + "bag", + "balance", + "balcony", + "ball", + "bamboo", + "banana", + "banner", + "bar", + "barely", + "bargain", + "barrel", + "base", + "basic", + "basket", + "battle", + "beach", + "bean", + "beauty", + "because", + "become", + "beef", + "before", + "begin", + "behave", + "behind", + "believe", + "below", + "belt", + "bench", + "benefit", + "best", + "betray", + "better", + "between", + "beyond", + "bicycle", + "bid", + "bike", + "bind", + "biology", + "bird", + "birth", + "bitter", + "black", + "blade", + "blame", + "blanket", + "blast", + "bleak", + "bless", + "blind", + "blood", + "blossom", + "blouse", + "blue", + "blur", + "blush", + "board", + "boat", + "body", + "boil", + "bomb", + "bone", + "bonus", + "book", + "boost", + "border", + "boring", + "borrow", + "boss", + "bottom", + "bounce", + "box", + "boy", + "bracket", + "brain", + "brand", + "brass", + "brave", + "bread", + "breeze", + "brick", + "bridge", + "brief", + "bright", + "bring", + "brisk", + "broccoli", + "broken", + "bronze", + "broom", + "brother", + "brown", + "brush", + "bubble", + "buddy", + "budget", + "buffalo", + "build", + "bulb", + "bulk", + "bullet", + "bundle", + "bunker", + "burden", + "burger", + "burst", + "bus", + "business", + "busy", + "butter", + "buyer", + "buzz", + "cabbage", + "cabin", + "cable", + "cactus", + "cage", + "cake", + "call", + "calm", + "camera", + "camp", + "can", + "canal", + "cancel", + "candy", + "cannon", + "canoe", + "canvas", + "canyon", + "capable", + "capital", + "captain", + "car", + "carbon", + "card", + "cargo", + "carpet", + "carry", + "cart", + "case", + "cash", + "casino", + "castle", + "casual", + "cat", + "catalog", + "catch", + "category", + "cattle", + "caught", + "cause", + "caution", + "cave", + "ceiling", + "celery", + "cement", + "census", + "century", + "cereal", + "certain", + "chair", + "chalk", + "champion", + "change", + "chaos", + "chapter", + "charge", + "chase", + "chat", + "cheap", + "check", + "cheese", + "chef", + "cherry", + "chest", + "chicken", + "chief", + "child", + "chimney", + "choice", + "choose", + "chronic", + "chuckle", + "chunk", + "churn", + "cigar", + "cinnamon", + "circle", + "citizen", + "city", + "civil", + "claim", + "clap", + "clarify", + "claw", + "clay", + "clean", + "clerk", + "clever", + "click", + "client", + "cliff", + "climb", + "clinic", + "clip", + "clock", + "clog", + "close", + "cloth", + "cloud", + "clown", + "club", + "clump", + "cluster", + "clutch", + "coach", + "coast", + "coconut", + "code", + "coffee", + "coil", + "coin", + "collect", + "color", + "column", + "combine", + "come", + "comfort", + "comic", + "common", + "company", + "concert", + "conduct", + "confirm", + "congress", + "connect", + "consider", + "control", + "convince", + "cook", + "cool", + "copper", + "copy", + "coral", + "core", + "corn", + "correct", + "cost", + "cotton", + "couch", + "country", + "couple", + "course", + "cousin", + "cover", + "coyote", + "crack", + "cradle", + "craft", + "cram", + "crane", + "crash", + "crater", + "crawl", + "crazy", + "cream", + "credit", + "creek", + "crew", + "cricket", + "crime", + "crisp", + "critic", + "crop", + "cross", + "crouch", + "crowd", + "crucial", + "cruel", + "cruise", + "crumble", + "crunch", + "crush", + "cry", + "crystal", + "cube", + "culture", + "cup", + "cupboard", + "curious", + "current", + "curtain", + "curve", + "cushion", + "custom", + "cute", + "cycle", + "dad", + "damage", + "damp", + "dance", + "danger", + "daring", + "dash", + "daughter", + "dawn", + "day", + "deal", + "debate", + "debris", + "decade", + "december", + "decide", + "decline", + "decorate", + "decrease", + "deer", + "defense", + "define", + "defy", + "degree", + "delay", + "deliver", + "demand", + "demise", + "denial", + "dentist", + "deny", + "depart", + "depend", + "deposit", + "depth", + "deputy", + "derive", + "describe", + "desert", + "design", + "desk", + "despair", + "destroy", + "detail", + "detect", + "develop", + "device", + "devote", + "diagram", + "dial", + "diamond", + "diary", + "dice", + "diesel", + "diet", + "differ", + "digital", + "dignity", + "dilemma", + "dinner", + "dinosaur", + "direct", + "dirt", + "disagree", + "discover", + "disease", + "dish", + "dismiss", + "disorder", + "display", + "distance", + "divert", + "divide", + "divorce", + "dizzy", + "doctor", + "document", + "dog", + "doll", + "dolphin", + "domain", + "donate", + "donkey", + "donor", + "door", + "dose", + "double", + "dove", + "draft", + "dragon", + "drama", + "drastic", + "draw", + "dream", + "dress", + "drift", + "drill", + "drink", + "drip", + "drive", + "drop", + "drum", + "dry", + "duck", + "dumb", + "dune", + "during", + "dust", + "dutch", + "duty", + "dwarf", + "dynamic", + "eager", + "eagle", + "early", + "earn", + "earth", + "easily", + "east", + "easy", + "echo", + "ecology", + "economy", + "edge", + "edit", + "educate", + "effort", + "egg", + "eight", + "either", + "elbow", + "elder", + "electric", + "elegant", + "element", + "elephant", + "elevator", + "elite", + "else", + "embark", + "embody", + "embrace", + "emerge", + "emotion", + "employ", + "empower", + "empty", + "enable", + "enact", + "end", + "endless", + "endorse", + "enemy", + "energy", + "enforce", + "engage", + "engine", + "enhance", + "enjoy", + "enlist", + "enough", + "enrich", + "enroll", + "ensure", + "enter", + "entire", + "entry", + "envelope", + "episode", + "equal", + "equip", + "era", + "erase", + "erode", + "erosion", + "error", + "erupt", + "escape", + "essay", + "essence", + "estate", + "eternal", + "ethics", + "evidence", + "evil", + "evoke", + "evolve", + "exact", + "example", + "excess", + "exchange", + "excite", + "exclude", + "excuse", + "execute", + "exercise", + "exhaust", + "exhibit", + "exile", + "exist", + "exit", + "exotic", + "expand", + "expect", + "expire", + "explain", + "expose", + "express", + "extend", + "extra", + "eye", + "eyebrow", + "fabric", + "face", + "faculty", + "fade", + "faint", + "faith", + "fall", + "false", + "fame", + "family", + "famous", + "fan", + "fancy", + "fantasy", + "farm", + "fashion", + "fat", + "fatal", + "father", + "fatigue", + "fault", + "favorite", + "feature", + "february", + "federal", + "fee", + "feed", + "feel", + "female", + "fence", + "festival", + "fetch", + "fever", + "few", + "fiber", + "fiction", + "field", + "figure", + "file", + "film", + "filter", + "final", + "find", + "fine", + "finger", + "finish", + "fire", + "firm", + "first", + "fiscal", + "fish", + "fit", + "fitness", + "fix", + "flag", + "flame", + "flash", + "flat", + "flavor", + "flee", + "flight", + "flip", + "float", + "flock", + "floor", + "flower", + "fluid", + "flush", + "fly", + "foam", + "focus", + "fog", + "foil", + "fold", + "follow", + "food", + "foot", + "force", + "forest", + "forget", + "fork", + "fortune", + "forum", + "forward", + "fossil", + "foster", + "found", + "fox", + "fragile", + "frame", + "frequent", + "fresh", + "friend", + "fringe", + "frog", + "front", + "frost", + "frown", + "frozen", + "fruit", + "fuel", + "fun", + "funny", + "furnace", + "fury", + "future", + "gadget", + "gain", + "galaxy", + "gallery", + "game", + "gap", + "garage", + "garbage", + "garden", + "garlic", + "garment", + "gas", + "gasp", + "gate", + "gather", + "gauge", + "gaze", + "general", + "genius", + "genre", + "gentle", + "genuine", + "gesture", + "ghost", + "giant", + "gift", + "giggle", + "ginger", + "giraffe", + "girl", + "give", + "glad", + "glance", + "glare", + "glass", + "glide", + "glimpse", + "globe", + "gloom", + "glory", + "glove", + "glow", + "glue", + "goat", + "goddess", + "gold", + "good", + "goose", + "gorilla", + "gospel", + "gossip", + "govern", + "gown", + "grab", + "grace", + "grain", + "grant", + "grape", + "grass", + "gravity", + "great", + "green", + "grid", + "grief", + "grit", + "grocery", + "group", + "grow", + "grunt", + "guard", + "guess", + "guide", + "guilt", + "guitar", + "gun", + "gym", + "habit", + "hair", + "half", + "hammer", + "hamster", + "hand", + "happy", + "harbor", + "hard", + "harsh", + "harvest", + "hat", + "have", + "hawk", + "hazard", + "head", + "health", + "heart", + "heavy", + "hedgehog", + "height", + "hello", + "helmet", + "help", + "hen", + "hero", + "hidden", + "high", + "hill", + "hint", + "hip", + "hire", + "history", + "hobby", + "hockey", + "hold", + "hole", + "holiday", + "hollow", + "home", + "honey", + "hood", + "hope", + "horn", + "horror", + "horse", + "hospital", + "host", + "hotel", + "hour", + "hover", + "hub", + "huge", + "human", + "humble", + "humor", + "hundred", + "hungry", + "hunt", + "hurdle", + "hurry", + "hurt", + "husband", + "hybrid", + "ice", + "icon", + "idea", + "identify", + "idle", + "ignore", + "ill", + "illegal", + "illness", + "image", + "imitate", + "immense", + "immune", + "impact", + "impose", + "improve", + "impulse", + "inch", + "include", + "income", + "increase", + "index", + "indicate", + "indoor", + "industry", + "infant", + "inflict", + "inform", + "inhale", + "inherit", + "initial", + "inject", + "injury", + "inmate", + "inner", + "innocent", + "input", + "inquiry", + "insane", + "insect", + "inside", + "inspire", + "install", + "intact", + "interest", + "into", + "invest", + "invite", + "involve", + "iron", + "island", + "isolate", + "issue", + "item", + "ivory", + "jacket", + "jaguar", + "jar", + "jazz", + "jealous", + "jeans", + "jelly", + "jewel", + "job", + "join", + "joke", + "journey", + "joy", + "judge", + "juice", + "jump", + "jungle", + "junior", + "junk", + "just", + "kangaroo", + "keen", + "keep", + "ketchup", + "key", + "kick", + "kid", + "kidney", + "kind", + "kingdom", + "kiss", + "kit", + "kitchen", + "kite", + "kitten", + "kiwi", + "knee", + "knife", + "knock", + "know", + "lab", + "label", + "labor", + "ladder", + "lady", + "lake", + "lamp", + "language", + "laptop", + "large", + "later", + "latin", + "laugh", + "laundry", + "lava", + "law", + "lawn", + "lawsuit", + "layer", + "lazy", + "leader", + "leaf", + "learn", + "leave", + "lecture", + "left", + "leg", + "legal", + "legend", + "leisure", + "lemon", + "lend", + "length", + "lens", + "leopard", + "lesson", + "letter", + "level", + "liar", + "liberty", + "library", + "license", + "life", + "lift", + "light", + "like", + "limb", + "limit", + "link", + "lion", + "liquid", + "list", + "little", + "live", + "lizard", + "load", + "loan", + "lobster", + "local", + "lock", + "logic", + "lonely", + "long", + "loop", + "lottery", + "loud", + "lounge", + "love", + "loyal", + "lucky", + "luggage", + "lumber", + "lunar", + "lunch", + "luxury", + "lyrics", + "machine", + "mad", + "magic", + "magnet", + "maid", + "mail", + "main", + "major", + "make", + "mammal", + "man", + "manage", + "mandate", + "mango", + "mansion", + "manual", + "maple", + "marble", + "march", + "margin", + "marine", + "market", + "marriage", + "mask", + "mass", + "master", + "match", + "material", + "math", + "matrix", + "matter", + "maximum", + "maze", + "meadow", + "mean", + "measure", + "meat", + "mechanic", + "medal", + "media", + "melody", + "melt", + "member", + "memory", + "mention", + "menu", + "mercy", + "merge", + "merit", + "merry", + "mesh", + "message", + "metal", + "method", + "middle", + "midnight", + "milk", + "million", + "mimic", + "mind", + "minimum", + "minor", + "minute", + "miracle", + "mirror", + "misery", + "miss", + "mistake", + "mix", + "mixed", + "mixture", + "mobile", + "model", + "modify", + "mom", + "moment", + "monitor", + "monkey", + "monster", + "month", + "moon", + "moral", + "more", + "morning", + "mosquito", + "mother", + "motion", + "motor", + "mountain", + "mouse", + "move", + "movie", + "much", + "muffin", + "mule", + "multiply", + "muscle", + "museum", + "mushroom", + "music", + "must", + "mutual", + "myself", + "mystery", + "myth", + "naive", + "name", + "napkin", + "narrow", + "nasty", + "nation", + "nature", + "near", + "neck", + "need", + "negative", + "neglect", + "neither", + "nephew", + "nerve", + "nest", + "net", + "network", + "neutral", + "never", + "news", + "next", + "nice", + "night", + "noble", + "noise", + "nominee", + "noodle", + "normal", + "north", + "nose", + "notable", + "note", + "nothing", + "notice", + "novel", + "now", + "nuclear", + "number", + "nurse", + "nut", + "oak", + "obey", + "object", + "oblige", + "obscure", + "observe", + "obtain", + "obvious", + "occur", + "ocean", + "october", + "odor", + "off", + "offer", + "office", + "often", + "oil", + "okay", + "old", + "olive", + "olympic", + "omit", + "once", + "one", + "onion", + "online", + "only", + "open", + "opera", + "opinion", + "oppose", + "option", + "orange", + "orbit", + "orchard", + "order", + "ordinary", + "organ", + "orient", + "original", + "orphan", + "ostrich", + "other", + "outdoor", + "outer", + "output", + "outside", + "oval", + "oven", + "over", + "own", + "owner", + "oxygen", + "oyster", + "ozone", + "pact", + "paddle", + "page", + "pair", + "palace", + "palm", + "panda", + "panel", + "panic", + "panther", + "paper", + "parade", + "parent", + "park", + "parrot", + "party", + "pass", + "patch", + "path", + "patient", + "patrol", + "pattern", + "pause", + "pave", + "payment", + "peace", + "peanut", + "pear", + "peasant", + "pelican", + "pen", + "penalty", + "pencil", + "people", + "pepper", + "perfect", + "permit", + "person", + "pet", + "phone", + "photo", + "phrase", + "physical", + "piano", + "picnic", + "picture", + "piece", + "pig", + "pigeon", + "pill", + "pilot", + "pink", + "pioneer", + "pipe", + "pistol", + "pitch", + "pizza", + "place", + "planet", + "plastic", + "plate", + "play", + "please", + "pledge", + "pluck", + "plug", + "plunge", + "poem", + "poet", + "point", + "polar", + "pole", + "police", + "pond", + "pony", + "pool", + "popular", + "portion", + "position", + "possible", + "post", + "potato", + "pottery", + "poverty", + "powder", + "power", + "practice", + "praise", + "predict", + "prefer", + "prepare", + "present", + "pretty", + "prevent", + "price", + "pride", + "primary", + "print", + "priority", + "prison", + "private", + "prize", + "problem", + "process", + "produce", + "profit", + "program", + "project", + "promote", + "proof", + "property", + "prosper", + "protect", + "proud", + "provide", + "public", + "pudding", + "pull", + "pulp", + "pulse", + "pumpkin", + "punch", + "pupil", + "puppy", + "purchase", + "purity", + "purpose", + "purse", + "push", + "put", + "puzzle", + "pyramid", + "quality", + "quantum", + "quarter", + "question", + "quick", + "quit", + "quiz", + "quote", + "rabbit", + "raccoon", + "race", + "rack", + "radar", + "radio", + "rail", + "rain", + "raise", + "rally", + "ramp", + "ranch", + "random", + "range", + "rapid", + "rare", + "rate", + "rather", + "raven", + "raw", + "razor", + "ready", + "real", + "reason", + "rebel", + "rebuild", + "recall", + "receive", + "recipe", + "record", + "recycle", + "reduce", + "reflect", + "reform", + "refuse", + "region", + "regret", + "regular", + "reject", + "relax", + "release", + "relief", + "rely", + "remain", + "remember", + "remind", + "remove", + "render", + "renew", + "rent", + "reopen", + "repair", + "repeat", + "replace", + "report", + "require", + "rescue", + "resemble", + "resist", + "resource", + "response", + "result", + "retire", + "retreat", + "return", + "reunion", + "reveal", + "review", + "reward", + "rhythm", + "rib", + "ribbon", + "rice", + "rich", + "ride", + "ridge", + "rifle", + "right", + "rigid", + "ring", + "riot", + "ripple", + "risk", + "ritual", + "rival", + "river", + "road", + "roast", + "robot", + "robust", + "rocket", + "romance", + "roof", + "rookie", + "room", + "rose", + "rotate", + "rough", + "round", + "route", + "royal", + "rubber", + "rude", + "rug", + "rule", + "run", + "runway", + "rural", + "sad", + "saddle", + "sadness", + "safe", + "sail", + "salad", + "salmon", + "salon", + "salt", + "salute", + "same", + "sample", + "sand", + "satisfy", + "satoshi", + "sauce", + "sausage", + "save", + "say", + "scale", + "scan", + "scare", + "scatter", + "scene", + "scheme", + "school", + "science", + "scissors", + "scorpion", + "scout", + "scrap", + "screen", + "script", + "scrub", + "sea", + "search", + "season", + "seat", + "second", + "secret", + "section", + "security", + "seed", + "seek", + "segment", + "select", + "sell", + "seminar", + "senior", + "sense", + "sentence", + "series", + "service", + "session", + "settle", + "setup", + "seven", + "shadow", + "shaft", + "shallow", + "share", + "shed", + "shell", + "sheriff", + "shield", + "shift", + "shine", + "ship", + "shiver", + "shock", + "shoe", + "shoot", + "shop", + "short", + "shoulder", + "shove", + "shrimp", + "shrug", + "shuffle", + "shy", + "sibling", + "sick", + "side", + "siege", + "sight", + "sign", + "silent", + "silk", + "silly", + "silver", + "similar", + "simple", + "since", + "sing", + "siren", + "sister", + "situate", + "six", + "size", + "skate", + "sketch", + "ski", + "skill", + "skin", + "skirt", + "skull", + "slab", + "slam", + "sleep", + "slender", + "slice", + "slide", + "slight", + "slim", + "slogan", + "slot", + "slow", + "slush", + "small", + "smart", + "smile", + "smoke", + "smooth", + "snack", + "snake", + "snap", + "sniff", + "snow", + "soap", + "soccer", + "social", + "sock", + "soda", + "soft", + "solar", + "soldier", + "solid", + "solution", + "solve", + "someone", + "song", + "soon", + "sorry", + "sort", + "soul", + "sound", + "soup", + "source", + "south", + "space", + "spare", + "spatial", + "spawn", + "speak", + "special", + "speed", + "spell", + "spend", + "sphere", + "spice", + "spider", + "spike", + "spin", + "spirit", + "split", + "spoil", + "sponsor", + "spoon", + "sport", + "spot", + "spray", + "spread", + "spring", + "spy", + "square", + "squeeze", + "squirrel", + "stable", + "stadium", + "staff", + "stage", + "stairs", + "stamp", + "stand", + "start", + "state", + "stay", + "steak", + "steel", + "stem", + "step", + "stereo", + "stick", + "still", + "sting", + "stock", + "stomach", + "stone", + "stool", + "story", + "stove", + "strategy", + "street", + "strike", + "strong", + "struggle", + "student", + "stuff", + "stumble", + "style", + "subject", + "submit", + "subway", + "success", + "such", + "sudden", + "suffer", + "sugar", + "suggest", + "suit", + "summer", + "sun", + "sunny", + "sunset", + "super", + "supply", + "supreme", + "sure", + "surface", + "surge", + "surprise", + "surround", + "survey", + "suspect", + "sustain", + "swallow", + "swamp", + "swap", + "swarm", + "swear", + "sweet", + "swift", + "swim", + "swing", + "switch", + "sword", + "symbol", + "symptom", + "syrup", + "system", + "table", + "tackle", + "tag", + "tail", + "talent", + "talk", + "tank", + "tape", + "target", + "task", + "taste", + "tattoo", + "taxi", + "teach", + "team", + "tell", + "ten", + "tenant", + "tennis", + "tent", + "term", + "test", + "text", + "thank", + "that", + "theme", + "then", + "theory", + "there", + "they", + "thing", + "this", + "thought", + "three", + "thrive", + "throw", + "thumb", + "thunder", + "ticket", + "tide", + "tiger", + "tilt", + "timber", + "time", + "tiny", + "tip", + "tired", + "tissue", + "title", + "toast", + "tobacco", + "today", + "toddler", + "toe", + "together", + "toilet", + "token", + "tomato", + "tomorrow", + "tone", + "tongue", + "tonight", + "tool", + "tooth", + "top", + "topic", + "topple", + "torch", + "tornado", + "tortoise", + "toss", + "total", + "tourist", + "toward", + "tower", + "town", + "toy", + "track", + "trade", + "traffic", + "tragic", + "train", + "transfer", + "trap", + "trash", + "travel", + "tray", + "treat", + "tree", + "trend", + "trial", + "tribe", + "trick", + "trigger", + "trim", + "trip", + "trophy", + "trouble", + "truck", + "true", + "truly", + "trumpet", + "trust", + "truth", + "try", + "tube", + "tuition", + "tumble", + "tuna", + "tunnel", + "turkey", + "turn", + "turtle", + "twelve", + "twenty", + "twice", + "twin", + "twist", + "two", + "type", + "typical", + "ugly", + "umbrella", + "unable", + "unaware", + "uncle", + "uncover", + "under", + "undo", + "unfair", + "unfold", + "unhappy", + "uniform", + "unique", + "unit", + "universe", + "unknown", + "unlock", + "until", + "unusual", + "unveil", + "update", + "upgrade", + "uphold", + "upon", + "upper", + "upset", + "urban", + "urge", + "usage", + "use", + "used", + "useful", + "useless", + "usual", + "utility", + "vacant", + "vacuum", + "vague", + "valid", + "valley", + "valve", + "van", + "vanish", + "vapor", + "various", + "vast", + "vault", + "vehicle", + "velvet", + "vendor", + "venture", + "venue", + "verb", + "verify", + "version", + "very", + "vessel", + "veteran", + "viable", + "vibrant", + "vicious", + "victory", + "video", + "view", + "village", + "vintage", + "violin", + "virtual", + "virus", + "visa", + "visit", + "visual", + "vital", + "vivid", + "vocal", + "voice", + "void", + "volcano", + "volume", + "vote", + "voyage", + "wage", + "wagon", + "wait", + "walk", + "wall", + "walnut", + "want", + "warfare", + "warm", + "warrior", + "wash", + "wasp", + "waste", + "water", + "wave", + "way", + "wealth", + "weapon", + "wear", + "weasel", + "weather", + "web", + "wedding", + "weekend", + "weird", + "welcome", + "west", + "wet", + "whale", + "what", + "wheat", + "wheel", + "when", + "where", + "whip", + "whisper", + "wide", + "width", + "wife", + "wild", + "will", + "win", + "window", + "wine", + "wing", + "wink", + "winner", + "winter", + "wire", + "wisdom", + "wise", + "wish", + "witness", + "wolf", + "woman", + "wonder", + "wood", + "wool", + "word", + "work", + "world", + "worry", + "worth", + "wrap", + "wreck", + "wrestle", + "wrist", + "write", + "wrong", + "yard", + "year", + "yellow", + "you", + "young", + "youth", + "zebra", + "zero", + "zone", + "zoo", +}; + +} // namespace bitflash + +#endif diff --git a/src/makefile.mingw b/src/makefile.mingw index ae533ef..e4dee59 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -92,4 +92,11 @@ bitflash.exe: $(IMGUI_OBJS) $(NODE_OBJS) $(GUI_OBJS) @echo "Built: bitflash.exe" clean: - rm -rf obj bitflash.exe + rm -rf obj bitflash.exe test_bip32.exe + +test_bip32.exe: test_bip32.cpp bip32.cpp bip32.h bip39_english.h + $(CXX) $(CXXFLAGS) -o $@ test_bip32.cpp bip32.cpp -lssl -lcrypto -lcrypt32 + @echo "Built: test_bip32.exe" + +tests: test_bip32.exe + ./test_bip32.exe diff --git a/src/test_bip32.cpp b/src/test_bip32.cpp new file mode 100644 index 0000000..610a651 --- /dev/null +++ b/src/test_bip32.cpp @@ -0,0 +1,130 @@ +// Standalone tests for BIP39/BIP32 primitives. +// +// Build: +// g++ -std=gnu++14 test_bip32.cpp bip32.cpp -lssl -lcrypto -o test_bip32 + +#include "bip32.h" + +#include +#include +#include +#include + +using namespace bitflash; + +static int g_fail = 0; + +#define CHECK(cond, name) do { \ + if (cond) { printf(" ok %s\n", name); } \ + else { printf(" FAIL %s\n", name); g_fail++; } \ +} while (0) + +static int HexDigit(char c) +{ + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return -1; +} + +static std::vector FromHex(const std::string& s) +{ + std::vector out; + if (s.size() % 2 != 0) + return out; + out.reserve(s.size() / 2); + for (size_t i = 0; i < s.size(); i += 2) + { + int hi = HexDigit(s[i]); + int lo = HexDigit(s[i + 1]); + if (hi < 0 || lo < 0) + return std::vector(); + out.push_back((unsigned char)((hi << 4) | lo)); + } + return out; +} + +static std::string ToHex(const std::vector& v) +{ + static const char* hex = "0123456789abcdef"; + std::string out; + out.reserve(v.size() * 2); + for (unsigned char c : v) + { + out.push_back(hex[c >> 4]); + out.push_back(hex[c & 0x0f]); + } + return out; +} + +int main() +{ + std::string err; + + printf("bip39_entropy_to_mnemonic\n"); + { + std::vector entropy(16, 0); + std::string mnemonic; + CHECK(BIP39EntropyToMnemonic(entropy, mnemonic, err), "zero entropy encodes"); + CHECK(mnemonic == + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", + "matches BIP39 vector"); + } + + printf("bip39_validation\n"); + { + std::string normalized; + CHECK(BIP39ValidateMnemonic( + " Abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about ", + normalized, err), + "valid phrase normalizes"); + CHECK(normalized == + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", + "normalized text matches"); + CHECK(!BIP39ValidateMnemonic( + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon", + normalized, err), + "bad checksum rejected"); + } + + printf("bip39_seed\n"); + { + std::vector seed; + const std::string mnemonic = + "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; + CHECK(BIP39MnemonicToSeed(mnemonic, "TREZOR", seed, err), "mnemonic derives seed"); + CHECK(ToHex(seed) == + "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e5349553" + "1f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04", + "matches BIP39 seed vector"); + } + + printf("bip32_master\n"); + { + std::vector seed = FromHex("000102030405060708090a0b0c0d0e0f"); + BIP32PrivateNode master; + CHECK(BIP32MasterFromSeed(seed, master, err), "master key derives"); + CHECK(ToHex(master.privateKey) == + "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35", + "matches BIP32 master private key"); + CHECK(ToHex(master.chainCode) == + "873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508", + "matches BIP32 master chain code"); + + BIP32PrivateNode childA, childB; + CHECK(BIP32DeriveHardenedChild(master, 0, childA, err), "hardened child derives"); + CHECK(BIP32DeriveHardenedChild(master, 0, childB, err), "hardened child re-derives"); + CHECK(childA.privateKey == childB.privateKey && + childA.chainCode == childB.chainCode, + "same child path is deterministic"); + CHECK(childA.privateKey != master.privateKey && + childA.chainCode != master.chainCode, + "child differs from parent"); + CHECK(!BIP32DeriveHardenedChild(master, 0x80000000U, childA, err), + "pre-hardened index rejected"); + } + + printf("\n%s (%d failures)\n", + g_fail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", g_fail); + return g_fail == 0 ? 0 : 1; +} -- cgit v1.2.3 From 24ed292f0524f1bc77c317b60d7ecf265596b3dd Mon Sep 17 00:00:00 2001 From: Bitflash Date: Sat, 1 Aug 2026 12:23:31 -0300 Subject: diag: let the node say what is wrong with it (#81) * Bump to 1.2.11 One change, and it is the reason a node on Windows kept collecting peers it could not hear. FD_SETSIZE was never defined in this tree, so it defaulted to 64 and select() could watch the listen socket plus 63 peers -- everything past that stayed connected and was never read again. Windows FD_SET stops adding once its array is full and says nothing, so there was no error to notice. Because new connections go on the end of vNodes, it was always the newest connection that starved, including the ones dialed to fix connectivity. Measured on two nodes: 277 and 90 CNode objects against 93 and 90 live sockets, 316 and 355 sockets in a bound-but-never-connected state, and a status bar reporting hundreds of peers for a node really talking to thirty. 1.2.11 raises FD_SETSIZE to 1024 on Windows, caps connections at 125, drops a node stuck undeliverable after 60 seconds instead of holding it forever, stops answering a failed select() with POSIX code that has no meaning on Windows, and warns when there are more peers than select can watch. * diag: let the node say what is wrong with it Every hard problem in this project so far was found from outside the node -- sockets read over WMI, committed memory compared against a README, a grep over somebody debug.log. In each case the node knew and had no way to say so. One report, rendered identically for the GUI panel and the log: peers held vs peers actually watched by select(), blocks received and how many arrived without a parent, proof-of-work mode with the live miner thread count, and per peer the age of the last message in each direction plus anything stuck unsent. --- Makefile | 2 +- src/gui.cpp | 38 +++++++++++++++++++ src/main.cpp | 7 ++++ src/net.cpp | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/net.h | 19 ++++++++++ 5 files changed, 182 insertions(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index d436885..0bc5892 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.10 +VERSION := 1.2.11 # ---- Linux ---------------------------------------------------------------- diff --git a/src/gui.cpp b/src/gui.cpp index 53cb6db..db6b69e 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -50,6 +50,7 @@ static int64 g_lastWalletRefresh = 0; static bool g_showSend = false; static bool g_showOptions = false; static bool g_showAbout = false; +static bool g_showDiagnostics = false; static bool g_needRefresh = true; static char g_sendAddr[128] = {}; @@ -310,6 +311,7 @@ static void DrawMainWindow() ImGui::EndMenu(); } if (ImGui::MenuItem("Options")) g_showOptions = true; + if (ImGui::MenuItem("Diagnostics")) g_showDiagnostics = true; if (ImGui::MenuItem("About")) g_showAbout = true; ImGui::EndMenuBar(); } @@ -815,6 +817,41 @@ static void DrawOptionsDialog() // --------------------------------------------------------------------------- // About dialog // --------------------------------------------------------------------------- +// What the node knows about itself, in the words it writes to the log. Same +// text in both places on purpose: what a user pastes into an issue is then +// exactly what a developer has already read a hundred times. +static void DrawDiagnosticsDialog() +{ + if (!g_showDiagnostics) return; + ImGui::SetNextWindowSize(ImVec2(720.0f, 460.0f), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), + ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); + if (ImGui::Begin("Diagnostics", &g_showDiagnostics, ImGuiWindowFlags_NoCollapse)) + { + // Rebuilt at most once a second: it walks every peer and takes their + // send locks, which is not something to do at frame rate. + static std::string strReport; + static int64 nLastBuilt = 0; + if (GetTime() != nLastBuilt) + { + nLastBuilt = GetTime(); + strReport = GetDiagnosticsText(); + } + + if (ImGui::Button("Copy to clipboard", ImVec2(160.0f, 0.0f))) + ImGui::SetClipboardText(strReport.c_str()); + ImGui::SameLine(); + ImGui::TextDisabled("The same report goes to debug.log every ten minutes."); + ImGui::Separator(); + + ImGui::BeginChild("##diagtext", ImVec2(0.0f, 0.0f), false, + ImGuiWindowFlags_HorizontalScrollbar); + ImGui::TextUnformatted(strReport.c_str()); + ImGui::EndChild(); + } + ImGui::End(); +} + static void DrawAboutDialog() { if (!g_showAbout) return; @@ -921,6 +958,7 @@ int RunGUI(int argc, char* argv[]) DrawMainWindow(); DrawSendDialog(); DrawOptionsDialog(); + DrawDiagnosticsDialog(); DrawAboutDialog(); DrawStatusBar(); diff --git a/src/main.cpp b/src/main.cpp index 5610de9..1a4c9ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1494,6 +1494,11 @@ bool CBlock::AcceptBlock() bool ProcessBlock(CNode* pfrom, CBlock* pblock) { + // Counted before any check, so the ratio below is against everything that + // arrived rather than everything that was any good. + if (pfrom) + nBlocksReceived++; + // Check for duplicate uint256 hash = pblock->GetHash(); if (mapBlockIndex.count(hash)) @@ -1512,6 +1517,8 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) if (!mapBlockIndex.count(pblock->hashPrevBlock)) { printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,14).c_str()); + if (pfrom) + nBlocksWithoutParent++; mapOrphanBlocks.insert(make_pair(hash, pblock)); mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock)); diff --git a/src/net.cpp b/src/net.cpp index 5ef8316..19893ee 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -46,6 +46,96 @@ CCriticalSection cs_mapRelay; map mapAlreadyAskedFor; string strBtfConnect; // .btf peer to keep connected to (from /connectbtf) +int nPeersWatched = 0; +int64 nBlocksReceived = 0; +int64 nBlocksWithoutParent = 0; +static int64 nNodeStartTime = 0; + +// Defined further down, next to the counter it reads. The miner keeps its own +// live count -- threads bump it on the way in and on the way out -- which is +// the honest number here: how many are hashing now, not how many were asked to. +static int MinersRunningCount(); + +// Seconds rendered the way a person reads them off a screen. +static string FormatAge(int64 nSeconds) +{ + if (nSeconds < 0) return "never"; + if (nSeconds < 60) return strprintf("%llds", (long long)nSeconds); + if (nSeconds < 3600) + return strprintf("%lldm%02llds", (long long)(nSeconds / 60), (long long)(nSeconds % 60)); + return strprintf("%lldh%02lldm", (long long)(nSeconds / 3600), (long long)((nSeconds % 3600) / 60)); +} + +string GetDiagnosticsText() +{ + int64 nNow = GetTime(); + string str; + + int nInbound = 0, nHeld = 0; + vector vCopy; + CRITICAL_BLOCK(cs_vNodes) + { + vCopy = vNodes; + nHeld = (int)vNodes.size(); + foreach(CNode* pnode, vNodes) + if (pnode->fInbound) + nInbound++; + } + + int nMedian = GetPeerMedianHeight(); + + str += "Bitflash node diagnostics\n"; + str += strprintf(" uptime %s\n", + FormatAge(nNodeStartTime ? nNow - nNodeStartTime : -1).c_str()); + if (nMedian < 0) + str += strprintf(" height %d (no peer has said where it is)\n", nBestHeight); + else + str += strprintf(" height %d (peers report %d, %s)\n", + nBestHeight, nMedian, + nBestHeight >= nMedian ? "level or ahead" + : strprintf("behind by %d", nMedian - nBestHeight).c_str()); + str += strprintf(" peers held %d (%d inbound, %d outbound)\n", + nHeld, nInbound, nHeld - nInbound); + + // The number that would have made the deafness obvious. Anything held but + // not watched is a socket this node will never read again. + str += strprintf(" peers watched %d of %d that select() can hold%s\n", + nPeersWatched, (int)FD_SETSIZE - 1, + nHeld > nPeersWatched ? " <-- NOT ALL PEERS ARE BEING READ" : ""); + + if (nBlocksReceived > 0) + str += strprintf(" blocks received %lld (%lld arrived without a parent, %.1f%%)\n", + (long long)nBlocksReceived, (long long)nBlocksWithoutParent, + 100.0 * nBlocksWithoutParent / nBlocksReceived); + else + str += " blocks received 0\n"; + + int nMining = MinersRunningCount(); + str += strprintf(" proof of work %s mode%s\n", + RandomXFastReady() ? "fast (2 GB dataset)" : "light (256 MB cache)", + nMining > 0 + ? strprintf(", mining on %d thread(s), about %d MB", + nMining, + (RandomXFastReady() ? 2080 : 256) + 2 * nMining).c_str() + : ", not mining"); + + str += "\n peer dir height last recv last send unsent\n"; + foreach(CNode* pnode, vCopy) + { + int nSendSize = 0; + TRY_CRITICAL_BLOCK(pnode->cs_vSend) + nSendSize = (int)pnode->vSend.size(); + str += strprintf(" %-28s %-4s %6d %10s %10s %7d\n", + pnode->addr.ToString().substr(0, 28).c_str(), + pnode->fInbound ? "in" : "out", + pnode->nStartingHeight, + FormatAge(pnode->nLastRecv ? nNow - pnode->nLastRecv : -1).c_str(), + FormatAge(pnode->nLastSend ? nNow - pnode->nLastSend : -1).c_str(), + nSendSize); + } + return str; +} + bool GetMyExternalIP(unsigned int& ipRet) { @@ -1058,6 +1148,24 @@ void ThreadSocketHandler2(void* parg) (int)vNodes.size() - (int)FD_SETSIZE + 1); } } + nPeersWatched = (int)nWatched - 1; // less the listen socket + } + + // Say the state of the node out loud now and then, so a log pulled off + // a machine three weeks later still answers "was it hearing anybody". + { + static int64 nLastReport = 0; + // Wound forward on the first pass so the first report lands about a + // minute in, once peers have had time to connect. A report written + // at second zero says nothing, and waiting ten minutes for the + // first one is ten minutes of a log that cannot answer anything. + if (nLastReport == 0) + nLastReport = GetTime() - 9 * 60; + if (GetTime() - nLastReport > 10 * 60) + { + nLastReport = GetTime(); + printf("%s\n", GetDiagnosticsText().c_str()); + } } vfThreadRunning[0] = false; @@ -1432,6 +1540,14 @@ void ThreadMessageHandler2(void* parg) static CCriticalSection cs_nMinersRunning; static int nMinersRunning = 0; +static int MinersRunningCount() +{ + int n = 0; + CRITICAL_BLOCK(cs_nMinersRunning) + n = nMinersRunning; + return n; +} + void ThreadBitcoinMiner(void* parg) { int nThreadId = (int)(intptr_t)parg; @@ -1490,6 +1606,7 @@ int StartMinerThreads() bool StartNode(string& strError) { strError = ""; + nNodeStartTime = GetTime(); // Sockets startup WSADATA wsadata; diff --git a/src/net.h b/src/net.h index 01f314d..bd4eb77 100644 --- a/src/net.h +++ b/src/net.h @@ -102,6 +102,25 @@ static const int BTF_PING_INTERVAL_SECS = 10 * 60; static const int BTF_BEHIND_GRACE_SECS = 5 * 60; static const int BTF_BEHIND_WARN_INTERVAL_SECS = 5 * 60; +// --- Self-diagnosis ------------------------------------------------------- +// +// A node that has stopped working looks exactly like a node with nothing to +// do. That has cost this project real time more than once: a node deaf to +// most of its peers, a miner allocating one RandomX dataset per thread, a +// third of arriving blocks missing their parent -- each was found from +// outside, by reading the process's sockets or its memory from another +// machine, because the node itself had no way to say so. +// +// These counters exist so it can. Cheap to keep, and they name the failures +// that actually happened rather than the ones that sound impressive. +extern int nPeersWatched; // peers in the last select() set +extern int64 nBlocksReceived; // blocks handed to ProcessBlock +extern int64 nBlocksWithoutParent; // ...of those, how many arrived orphaned + +// One report, rendered the same way for the GUI panel and the log, so what a +// user pastes into an issue is what a developer already knows how to read. +string GetDiagnosticsText(); + // Defined in main.cpp. Declared here because CNode announces it in the version // message, and net.h is included before main.h. extern int nBestHeight; -- cgit v1.2.3 From 19ecd6ad61b560d92d82ed5a79b5217d64f97327 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Sat, 1 Aug 2026 17:59:05 -0300 Subject: Bump to 1.2.12 (#97) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Version bump for the 1.2.12 release. One line of Makefile; the release notes live here. ## The reason this release is not optional **#87 — a node that was mining before 1.2.11 can come back as a relay and never say so.** The 1.2.11 mining rework left `fGenerateBitcoins` readable on its own: a wallet carrying that flag from an older build, with no mining mode stored beside it, loads as "not mining" and the window shows nothing wrong. It happened here, on a real node, and it was found only because somebody looked at the hashrate. Anyone running 1.2.11 who mined on an earlier build should assume they are affected. ## Recovery phrase (#93, #96) Twelve words that bring a wallet back. Proved end to end before merging: a live wallet was paid on a derived address, `wallet.dat` was deleted, and the coin came back from the phrase alone. - `-newphrase` creates a phrase, installs the seed, fills the key pool from it and shows the words once. It refuses when a seed already exists. - `-restorephrase="WORDS"` installs the seed and walks forward in batches of 100, rescanning after each and stopping when a batch turns up nothing. `-restoredepth=N` to look further. - `-newaddress` prints the next receiving address; `-showderived=N` lists what a phrase produces. - The same two operations are reachable from the window. **What the phrase does not cover, stated plainly:** keys that existed before the seed was installed — including the wallet's original default address — are not derived from it and do not come back from the words. The commands say this at the point of use. Keep the `wallet.dat` backup as well; the phrase is a second line, not a replacement. The words are printed to the terminal only, never to `debug.log`. ## Wallet safety - **#88** — `ScanForWalletTransactions` plus `-rescan`: the node can now walk the chain for coins a key owns but the wallet never saw. `-importwallet` scans too. Without this, restoring from a phrase would have derived the right keys and found nothing. - **#89, #90** — a backup panel in the window, with the default backup written outside the directory it protects. - **#95** — a scan with no chain data loaded is refused instead of reporting "no transactions found", which read as a verdict to somebody who had just lost a wallet. ## Tests and diagnostics **#91** wallet key pool self-test, **#92** self-test output where the person running it can see it, **#94** MSYS2 argument conversion (use `-selftest=...`, not `/selftest=...`, under MSYS2). `make tests` runs the BIP32/BIP39 vectors and both wallet self-tests on Linux and Windows. ## Still not fixed The socket accounting shipped in 1.2.11 is instrumentation, not a fix — sockets still leak. The three obvious causes have been measured and eliminated; the next step is reading a real node's diagnostic report, not another guess. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0bc5892..01fe4f4 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.11 +VERSION := 1.2.12 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From a45ed6918bc69c938e86e7107a038fd830a1cfde Mon Sep 17 00:00:00 2001 From: Bitflash Date: Sat, 1 Aug 2026 21:49:24 -0300 Subject: Bump to 1.2.13 (#105) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two things a node could do wrong without ever saying so: close a peer's socket twice, and hand out addresses a recovery phrase cannot reproduce. ## If you created a recovery phrase on 1.2.12, do this first Run, with the same twelve words: ``` Bitflash.exe -restorephrase="your twelve words here" ``` 1.2.12 installed the seed but left the wallet's visible address as the old random key, and left the old random key pool in place. The window said a recovery phrase existed while the next address the wallet handed out — a mining payout included — could be one the words cannot reproduce. Restoring with the same phrase repairs it: the pool is cleared, and the default address becomes a derived one. Coins already sitting on pre-phrase addresses stay where they are. They are still yours, still spendable, and still **not** covered by the words — which is why `wallet.dat` backups keep mattering. The wallet now names that address `Your Address (created before the recovery phrase)` instead of leaving two entries both called `Your Address` with only one of them recoverable. Thanks to **@mtg0001**, who found this within hours of 1.2.12 shipping (#102). ## A peer's socket was closed twice, and the second close hit whoever had the number `CNode::Disconnect()` closed the socket and left the handle number in the object; the destructor then closed that same number again. There is no assignment of `INVALID_SOCKET` to that field anywhere in the tree, so the guard meant to prevent this never fired. A double close is not a harmless no-op. This node opens hundreds of sockets a minute, and Windows reissues a handle number as soon as its last close lands — so the second close takes down a connection that now belongs to something else entirely. The same omission left a closed handle in the `select()` set, where it makes `select()` fail on every iteration for as long as that node is in the list. The node then spends its socket loop in an error path instead of reading its peers. **That is the deaf-node behaviour this project has been chasing since 1.2.7**, and the `dropping node: its socket is no longer valid` line in the log is the recovery path, not the disease. Measured, two nodes on the same machine and the same network, stopped at matched socket volume: | | sockets opened | failed closes | `no longer valid` | peers held | |---|---|---|---|---| | without the fix | 552 | 4 | **741** | 11 | | **with the fix** | 547 | **0** | **0** | **21** | Half the peers, on the same machine, at the same minute. All 741 drops were the same peer, over and over — one dead handle in the set is enough. ## The socket leak was already fixed, and the way it was being measured was wrong Earlier notes, including 1.2.12's, said sockets were still leaking. They were not. Windows lists a wildcard-bound socket **twice** in `Get-NetTCPConnection` — once for the binding (`0.0.0.0:port`, state `Bound`) and once for the connection — and 35 of one node's 38 `Bound` rows shared a local port with one of its own established connections. Counting those rows makes the number climb whenever the node talks to more peers, which is why the fix that worked looked like it had done nothing. Counting **orphans** instead — a `Bound` row whose port appears nowhere else in that process — measured on three machines the same evening: | node | version | uptime | orphans | |---|---|---|---| | 32-core miner | 1.2.10 | 26 h | **1262**, still taking on 30–90 an hour | | second miner | 1.2.11 | 4h40m | 3 | | test bench | 1.2.12 | 2 min | 3 | The leak was real and **1.2.11 ended it**. If you are still on 1.2.10 or earlier, that alone is worth the upgrade. ## Also in this release - The diagnostics report now says why a close failed, per error code and per site, totals what the node believes it is holding, and counts a handle handed out while some part of the program still claims it (#98, #100, #101). - Every header is listed in both makefiles (#99). `sockcount.h` was missing, so editing it rebuilt some objects and not others and left two layouts of the same shared struct in one binary — a warning in the middle of a build log and nothing else. ## Downloads | File | Platform | Notes | |------|----------|-------| | `Bitflash-1.2.13-windows.zip` | Windows x86_64 | Extract and run | | `Bitflash-1.2.13-x86_64.AppImage` | Linux x86_64 | Desktop/GUI — `chmod +x` and run | | `bitflash-node-1.2.13-x86_64` | Linux x86_64 | Headless server node, no libGL or FUSE | Verify with `sha256sum -c SHA256SUMS`. Everything in [v1.2.12](https://github.com/Bitflash-sh/bitflash/releases/tag/v1.2.12) is included. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 01fe4f4..b0f22f7 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.12 +VERSION := 1.2.13 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From 4b2416b7315d76a2abd1a0ac0b72b3d1ef0ff6c6 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Sun, 2 Aug 2026 14:04:42 -0300 Subject: Bump to 1.2.14 (#116) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A block had no size limit, spending could move coins onto a key your recovery phrase cannot reproduce, and one peer could hold up the whole node with a message it never finished sending. All three are fixed here, and all three were found by auditing the tree rather than by anyone hitting them. ## Blocks now have a size limit — and this one is consensus `CheckBlock()` measured a block against `MAX_SIZE`, the serializer's generic 32 MB guard. There was no `MAX_BLOCK_SIZE` anywhere in the tree: Bitcoin's 1 MB cap arrived in 0.3.x, after the 0.1.0 this project came from, so the inheritance was simply missing. A miner could produce a 32 MB block and every node would download, verify and store it. The cap is now **1 MB**, chosen against the chain rather than tradition. Reading all 5709 blocks out of `blk0001.dat`: | | | |---|---| | largest block ever mined | 34,290 bytes | | median | 216 bytes | | p99 | 14,451 bytes | 1 MB leaves **29× of headroom** over the largest block this chain has ever carried, so nothing existing is rejected. A node built with the rule then synced genesis → 5706 on the live network with zero rejections, which is the same test that once caught BIP30 rejecting a real block at height 859. **Because it is consensus, it matters that you upgrade.** Until most nodes have it, a block above 1 MB would be accepted by old nodes and rejected by new ones — which is how a chain splits. Nobody is mining such blocks today; the gap is worth closing before somebody does. ## Spending could put your change on a key the phrase cannot recover When a wallet spends, the leftover goes back to you as *change*. This tree sent change to **the same key as one of the coins being spent** — 0.1.0 behaviour, and a privacy problem long tracked as #23. With recovery phrases it became a way to lose money. If the coin being spent sat on a key created *before* the seed — the wallet's original default address, an imported key, anything older than `-newphrase` — then the change went back to that same pre-seed key. So spending quietly moved your balance onto a key the twelve words do not reproduce, in a wallet you believed the words covered. Change now comes from a newly derived, phrase-backed key. **If that derivation fails, the transaction is refused rather than created**, because a failed send is recoverable and unrecoverable change is not. Wallets with no seed keep the old behaviour exactly. Restore also now scans past the pre-generated key-pool window before accepting an empty batch as the end, so a restore cannot stop short while used addresses sit just beyond it. ## One peer could hold up the whole node `ProcessMessages` runs in a single thread that serves every peer. When a message header announced more bytes than had arrived, the old code consumed the header, inserted it back at the *front* of the receive buffer — an O(n) memmove on a buffer that could hold 256 MB — and then slept 100 ms **inside that shared thread**. A peer that announced a large message and dripped bytes could make every pass pay both costs, forever, while looking perfectly active to the inactivity reaper. The parser now reads the header from a copy without consuming it, never sleeps in the shared thread, and disconnects a peer that sits on an incomplete message for two minutes. The wire cap drops from 256 MB to `MAX_SIZE`. ## The rendezvous holds more than one registration A node's registration at a rendezvous relay was consumed by the first caller, and registering again *replaced* the previous one — so a node was reachable to exactly one peer at a time and unreachable for the whole gap between being paired and registering again. Measured on a live node: descriptors resolved 53 times out of 54, its own registrations paired 11 out of 12, and **half of every outbound dial failed**. All three relays now keep a queue per node and pair with the oldest registration still alive. **This is already deployed** — you get it without upgrading. The matching node-side change, which parks spare registrations, is deliberately **not** in this release: it measured worse in the field than the code it replaced and will not ship until that is explained. ## Restoring from a phrase now looks far enough Found by proving the change fix above with real coin, and caused by it. Restoring derived forward in batches of a hundred and stopped at the first batch that turned up nothing. The wallet digs a wider gap than that by itself: a restore leaves the derivation counter at the depth it scanned, the key pool derives a hundred more, and change takes the index after those. So the address used *after* a restore can sit two hundred indices past the last one used before it, with nothing in between. On a real wallet: receive, restore, spend once — the outputs land at indices 201 and 302. Restoring again reported ``` Restored: 1 transaction(s) across 201 derived addresses ``` and the spend was invisible, both the payment and the change. The money was derived and covered by the phrase; the search stopped short of it. Three quiet batches instead of one, and the same wallet reports `2 transaction(s) across 601 derived addresses`. Change returning to an input's key used to hide this, because that key sat at a low index the scan had already passed. Fixing recoverability moved change out to where the search stopped looking, so the two had to be fixed together. The gap is self-inflicted and grows with each restore, so a long enough history can still outrun a fixed number of quiet batches. `-restoredepth=N` looks as far as you ask. The structural fix is tracked separately. ## A headless node can finally spend `SendMoney()` has been in this tree since 0.1.0 and only the window ever called it, so a node without a screen could be paid and could never pay — it could hold a balance with no way to move it. Found while trying to prove the change fix, which needs a spend. ``` bitflash -sendto=ADDRESS,AMOUNT ``` Refuses an address that does not decode, an amount that is zero, negative or not a number, and a wallet whose chain is not loaded — all before touching the wallet. A transaction created while the node is stopped is not broadcast until the node starts. ## Also - `-help` printed nothing at all on Windows. This tree remaps `printf` to the debug-log writer, and a `-mwindows` binary has no console, so the one command whose job is to tell you something returned 0 in silence. - The README described a program from several releases ago — deterministic restore listed as an open issue, mining mode described as forgotten between restarts, and every flag written in the slash form that MSYS2 rewrites into a path. - Diagnostics now report why a socket close failed, per error code and per site, and flag a handle handed back while some part of the program still claims it. ## Downloads | File | Platform | Notes | |------|----------|-------| | `Bitflash-1.2.14-windows.zip` | Windows x86_64 | Extract and run | | `Bitflash-1.2.14-x86_64.AppImage` | Linux x86_64 | Desktop/GUI — `chmod +x` and run | | `bitflash-node-1.2.14-x86_64` | Linux x86_64 | Headless server node, no libGL or FUSE | Verify with `sha256sum -c SHA256SUMS`. Everything in [v1.2.13](https://github.com/Bitflash-sh/bitflash/releases/tag/v1.2.13) is included. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index b0f22f7..858313a 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.13 +VERSION := 1.2.14 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From 1aee805b232a33484e3db1dc8ea4bfb3f585212e Mon Sep 17 00:00:00 2001 From: Bitflash Date: Mon, 3 Aug 2026 11:00:04 -0300 Subject: Bump to 1.2.15 (#120) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 858313a..a9630ed 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.14 +VERSION := 1.2.15 # ---- Linux ---------------------------------------------------------------- -- cgit v1.2.3 From f6c5b813075cae4228d241a3567e70b210504749 Mon Sep 17 00:00:00 2001 From: mtg0001 <106211915+mtg0001@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:18:01 -0300 Subject: Add release verification tooling (#108) Co-authored-by: Gilcimar Duarte --- .gitignore | 1 + Makefile | 14 ++++- README.md | 19 ++++++- docs/release-verification.md | 62 ++++++++++++++++++++ scripts/make-release-checksums.sh | 78 ++++++++++++++++++++++++++ scripts/verify-release.sh | 115 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 docs/release-verification.md create mode 100755 scripts/make-release-checksums.sh create mode 100755 scripts/verify-release.sh (limited to 'Makefile') diff --git a/.gitignore b/.gitignore index 1ec9099..111f7ba 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ Bitflash-*-windows.zip Bitflash-*.AppImage bitflash-node-*-x86_64 SHA256SUMS +SHA256SUMS.asc # Runtime data / logs debug.log diff --git a/Makefile b/Makefile index a9630ed..ea720f1 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,8 @@ # make linux build Bitflash-*-x86_64.AppImage # make windows build Bitflash-*-windows.zip (from MSYS2 UCRT64) # make tests build and run standalone unit tests +# make checksums create SHA256SUMS for release assets +# make verify-release TAG=v1.2.13 # make clean remove build artifacts ROOT := $(shell pwd) @@ -160,5 +162,15 @@ clean: tests: $(MAKE) -C src -f Makefile tests +checksums: + ./scripts/make-release-checksums.sh + +sign-checksums: + ./scripts/make-release-checksums.sh --sign $(if $(KEY),--local-user $(KEY),) + +verify-release: + ./scripts/verify-release.sh $(if $(TAG),$(TAG),latest) + .PHONY: linux windows clean appimage \ - tests deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx + tests checksums sign-checksums verify-release \ + deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx diff --git a/README.md b/README.md index 6601384..6446b3d 100644 --- a/README.md +++ b/README.md @@ -49,13 +49,30 @@ configuration — it connects automatically and starts syncing. **Windows:** extract the `-windows.zip` and run `Bitflash.exe`. -Every release ships a `SHA256SUMS` covering both assets. Verifying takes a second +Every release ships a `SHA256SUMS` covering the assets. Verifying takes a second and is worth doing: ```bash sha256sum -c SHA256SUMS ``` +For newer signed releases, verify the checksum file itself first: + +```bash +gpg --verify SHA256SUMS.asc SHA256SUMS +sha256sum -c SHA256SUMS +``` + +The helper below downloads the release assets, verifies `SHA256SUMS.asc` when it +is present, then checks the hashes: + +```bash +scripts/verify-release.sh latest +``` + +See [release verification](docs/release-verification.md) for the full release +audit flow and the maintainer signing step. + **Keep your node current.** Consensus rules have changed since the first releases — 1.2.1 fixed a bug that let anyone spend anyone's coins, and 1.2.2 added a per-block signature-operation cap. A node on an older build will accept diff --git a/docs/release-verification.md b/docs/release-verification.md new file mode 100644 index 0000000..ecacd5f --- /dev/null +++ b/docs/release-verification.md @@ -0,0 +1,62 @@ +# Release Verification + +Bitflash releases publish binaries and a `SHA256SUMS` file. The checksum file +proves that the file you downloaded matches the file the release page names. +A detached signature, `SHA256SUMS.asc`, proves that the checksum file itself was +signed by a trusted release key. + +That gives users two separate checks: + +1. `gpg --verify SHA256SUMS.asc SHA256SUMS` checks who signed the checksums. +2. `sha256sum -c SHA256SUMS` checks the binaries against those checksums. + +## User Check + +From a shell with `curl` or `wget` and `sha256sum`: + +```bash +scripts/verify-release.sh latest +``` + +For a specific release: + +```bash +scripts/verify-release.sh v1.2.13 +``` + +For release audits, require the signature: + +```bash +scripts/verify-release.sh v1.2.13 --require-signature +``` + +Older releases may not have `SHA256SUMS.asc`. In that case the script warns and +still checks file integrity. New release audits should use `--require-signature`. + +## Maintainer Flow + +After building release assets in the repository root: + +```bash +scripts/make-release-checksums.sh --sign --local-user RELEASE_KEY_ID +``` + +Upload all built assets plus: + +```text +SHA256SUMS +SHA256SUMS.asc +``` + +Keep the private signing key offline or on a dedicated release machine. Publish +the public key fingerprint in the release notes and keep using the same key for +future releases unless there is a clearly announced rotation. + +## Why This Matters + +`SHA256SUMS` alone protects against a broken download, but not against someone +replacing both a binary and the checksum file. Signing `SHA256SUMS` means an +attacker must also have the release signing key to make the replacement verify. + +This is not reproducible builds yet. It is the smaller, immediate step that +makes every release asset auditable by users before they run it. diff --git a/scripts/make-release-checksums.sh b/scripts/make-release-checksums.sh new file mode 100755 index 0000000..5b29e2d --- /dev/null +++ b/scripts/make-release-checksums.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +set -euo pipefail + +sign=0 +key="" + +usage() { + cat <<'EOF' +Usage: scripts/make-release-checksums.sh [--sign] [--local-user KEYID] + +Creates SHA256SUMS for release assets in the current directory: + Bitflash-*-windows.zip + Bitflash-*-x86_64.AppImage + bitflash-node-*-x86_64 + +With --sign, also creates SHA256SUMS.asc as a detached ASCII-armored GPG +signature. Upload both files with the release assets. +EOF +} + +while [ "$#" -gt 0 ]; do + case "$1" in + --sign) sign=1 ;; + --local-user) + [ "$#" -ge 2 ] || { echo "--local-user needs a key id" >&2; exit 2; } + key="$2" + shift + ;; + -h|--help) usage; exit 0 ;; + *) echo "unknown option: $1" >&2; usage >&2; exit 2 ;; + esac + shift +done + +if command -v sha256sum >/dev/null 2>&1; then + sha_cmd=(sha256sum) +elif command -v shasum >/dev/null 2>&1; then + sha_cmd=(shasum -a 256) +else + echo "missing required command: sha256sum or shasum" >&2 + exit 1 +fi + +assets=() +for pattern in \ + "Bitflash-*-windows.zip" \ + "Bitflash-*-x86_64.AppImage" \ + "bitflash-node-*-x86_64" +do + for file in $pattern; do + [ -e "$file" ] || continue + assets+=("$file") + done +done + +if [ "${#assets[@]}" -eq 0 ]; then + echo "no release assets found in $(pwd)" >&2 + exit 1 +fi + +printf '%s\n' "${assets[@]}" | LC_ALL=C sort | while IFS= read -r file; do + "${sha_cmd[@]}" "$file" +done > SHA256SUMS + +echo "Wrote SHA256SUMS" + +if [ "$sign" -eq 1 ]; then + if ! command -v gpg >/dev/null 2>&1; then + echo "missing required command: gpg" >&2 + exit 1 + fi + gpg_args=(--armor --detach-sign --output SHA256SUMS.asc) + if [ -n "$key" ]; then + gpg_args+=(--local-user "$key") + fi + gpg "${gpg_args[@]}" SHA256SUMS + echo "Wrote SHA256SUMS.asc" +fi diff --git a/scripts/verify-release.sh b/scripts/verify-release.sh new file mode 100755 index 0000000..23e71d1 --- /dev/null +++ b/scripts/verify-release.sh @@ -0,0 +1,115 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo="Bitflash-sh/bitflash" +tag="${1:-latest}" +require_signature=0 + +usage() { + cat <<'EOF' +Usage: scripts/verify-release.sh [tag|latest] [--require-signature] + +Downloads the release checksum file and every asset named in it, then verifies: + 1. SHA256SUMS.asc, if present, against SHA256SUMS with gpg. + 2. SHA256SUMS against the downloaded assets. + +Use --require-signature for release audits. Without it, older releases that +ship only SHA256SUMS are checked for integrity and reported as unsigned. +EOF +} + +for arg in "${@:2}"; do + case "$arg" in + --require-signature) require_signature=1 ;; + -h|--help) usage; exit 0 ;; + *) echo "unknown option: $arg" >&2; usage >&2; exit 2 ;; + esac +done + +if [ "$tag" = "-h" ] || [ "$tag" = "--help" ]; then + usage + exit 0 +fi + +need() { + if ! command -v "$1" >/dev/null 2>&1; then + echo "missing required command: $1" >&2 + exit 1 + fi +} + +need sed +need awk + +if command -v sha256sum >/dev/null 2>&1; then + sha_check=(sha256sum -c SHA256SUMS) +elif command -v shasum >/dev/null 2>&1; then + sha_check=(shasum -a 256 -c SHA256SUMS) +else + echo "missing required command: sha256sum or shasum" >&2 + exit 1 +fi + +download() { + local url="$1" + local out="$2" + if command -v curl >/dev/null 2>&1; then + curl -fsSL "$url" -o "$out" + elif command -v wget >/dev/null 2>&1; then + wget -q "$url" -O "$out" + else + echo "missing required command: curl or wget" >&2 + exit 1 + fi +} + +if [ "$tag" = "latest" ]; then + tag="$(download "https://api.github.com/repos/$repo/releases/latest" - | + sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | + head -1)" + if [ -z "$tag" ]; then + echo "could not resolve latest release tag" >&2 + exit 1 + fi +fi + +workdir="$(mktemp -d "${TMPDIR:-/tmp}/bitflash-release-verify.XXXXXX")" +cleanup() { rm -rf "$workdir"; } +trap cleanup EXIT + +base_url="https://github.com/$repo/releases/download/$tag" + +echo "Verifying Bitflash $tag" +echo "Working directory: $workdir" +cd "$workdir" + +download "$base_url/SHA256SUMS" SHA256SUMS + +if download "$base_url/SHA256SUMS.asc" SHA256SUMS.asc 2>/dev/null; then + if ! command -v gpg >/dev/null 2>&1; then + echo "SHA256SUMS.asc exists, but gpg is not installed" >&2 + exit 1 + fi + gpg --verify SHA256SUMS.asc SHA256SUMS + echo "Signature OK" +else + if [ "$require_signature" -eq 1 ]; then + echo "release does not publish SHA256SUMS.asc" >&2 + exit 1 + fi + echo "WARNING: no SHA256SUMS.asc found; checking hashes only" +fi + +awk '{print $2}' SHA256SUMS | while IFS= read -r file; do + file="${file#\*}" + file="${file#./}" + [ -z "$file" ] && continue + case "$file" in + */*|..*) echo "refusing unexpected checksum path: $file" >&2; exit 1 ;; + esac + echo "Downloading $file" + download "$base_url/$file" "$file" +done + +"${sha_check[@]}" +echo "Release assets OK" -- cgit v1.2.3 From 5ac1fd55eea9d4b5e9b34be50d3b684693e3a935 Mon Sep 17 00:00:00 2001 From: mtg0001 <106211915+mtg0001@users.noreply.github.com> Date: Tue, 4 Aug 2026 15:25:34 -0300 Subject: build: pin external source dependencies (#139) Co-authored-by: Gilcimar Duarte --- Makefile | 43 ++++++++++++++++++++++++++++++++++++------- docs/dependencies.md | 18 ++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 docs/dependencies.md (limited to 'Makefile') diff --git a/Makefile b/Makefile index ea720f1..0788b61 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,11 @@ NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") VERSION := 1.2.15 +SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1 +SECP256K1_COMMIT := 7fecac74aed8e1fd9078380d67dd04663705c989 +RANDOMX_REPO := https://github.com/tevador/RandomX +RANDOMX_COMMIT := 1e9d4b2df63fa6edf46b06789486e23c0fcaa55a + # ---- Linux ---------------------------------------------------------------- linux: deps-linux @@ -47,7 +52,13 @@ deps-secp256k1: @if [ ! -f /usr/local/lib/libsecp256k1.a ]; then \ echo "==> building libsecp256k1"; \ rm -rf $(ROOT)/secp256k1-build; \ - git clone --depth 1 https://github.com/bitcoin-core/secp256k1 $(ROOT)/secp256k1-build; \ + git init -q $(ROOT)/secp256k1-build; \ + cd $(ROOT)/secp256k1-build && \ + git remote add origin $(SECP256K1_REPO) && \ + git fetch -q --depth 1 origin $(SECP256K1_COMMIT) && \ + git checkout -q --detach FETCH_HEAD && \ + test "$$(git rev-parse HEAD)" = "$(SECP256K1_COMMIT)" && \ + echo "==> libsecp256k1 pinned at $(SECP256K1_COMMIT)" && \ cd $(ROOT)/secp256k1-build && ./autogen.sh && \ ./configure --enable-module-schnorrsig --enable-module-extrakeys \ --disable-shared --with-pic --disable-benchmark --disable-tests && \ @@ -61,7 +72,13 @@ deps-randomx: @if [ ! -f $(HOME)/RandomX/build/librandomx.a ]; then \ echo "==> building RandomX"; \ rm -rf $(HOME)/RandomX; \ - git clone --depth 1 https://github.com/tevador/RandomX $(HOME)/RandomX; \ + git init -q $(HOME)/RandomX; \ + cd $(HOME)/RandomX && \ + git remote add origin $(RANDOMX_REPO) && \ + git fetch -q --depth 1 origin $(RANDOMX_COMMIT) && \ + git checkout -q --detach FETCH_HEAD && \ + test "$$(git rev-parse HEAD)" = "$(RANDOMX_COMMIT)" && \ + echo "==> RandomX pinned at $(RANDOMX_COMMIT)" && \ mkdir -p $(HOME)/RandomX/build; \ cd $(HOME)/RandomX/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \ make -j$(NPROC) randomx; \ @@ -120,8 +137,14 @@ deps-windows: autoconf automake libtool @if [ ! -f deps/lib/libsecp256k1.a ]; then \ rm -rf secp256k1-build; \ - git clone --depth 1 https://github.com/bitcoin-core/secp256k1 secp256k1-build; \ - cd secp256k1-build && ./autogen.sh && \ + git init -q secp256k1-build; \ + cd secp256k1-build && \ + git remote add origin $(SECP256K1_REPO) && \ + git fetch -q --depth 1 origin $(SECP256K1_COMMIT) && \ + git checkout -q --detach FETCH_HEAD && \ + test "$$(git rev-parse HEAD)" = "$(SECP256K1_COMMIT)" && \ + echo "==> secp256k1 pinned at $(SECP256K1_COMMIT)" && \ + cd $(ROOT)/secp256k1-build && ./autogen.sh && \ ./configure --prefix=$(ROOT)/deps \ --enable-module-schnorrsig --enable-module-extrakeys \ --disable-shared --with-pic --disable-benchmark --disable-tests && \ @@ -132,9 +155,15 @@ deps-windows: fi @if [ ! -f RandomX/build/librandomx.a ]; then \ rm -rf RandomX; \ - git clone --depth 1 https://github.com/tevador/RandomX; \ - mkdir -p RandomX/build; \ - cd RandomX/build && cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release && \ + git init -q RandomX; \ + cd RandomX && \ + git remote add origin $(RANDOMX_REPO) && \ + git fetch -q --depth 1 origin $(RANDOMX_COMMIT) && \ + git checkout -q --detach FETCH_HEAD && \ + test "$$(git rev-parse HEAD)" = "$(RANDOMX_COMMIT)" && \ + echo "==> RandomX pinned at $(RANDOMX_COMMIT)" && \ + mkdir -p $(ROOT)/RandomX/build; \ + cd $(ROOT)/RandomX/build && cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release && \ make randomx; \ echo "==> RandomX done"; \ else \ diff --git a/docs/dependencies.md b/docs/dependencies.md new file mode 100644 index 0000000..9fd45b6 --- /dev/null +++ b/docs/dependencies.md @@ -0,0 +1,18 @@ +# Build Dependencies + +Bitflash links consensus-adjacent cryptographic and proof-of-work code from +external repositories. Fresh builds must not follow upstream `master` silently: +a changed upstream branch can break reproducible builds or change behavior in +code that every node relies on. + +The top-level `Makefile` pins source dependencies by full commit hash: + +| dependency | repository | pinned commit | +|---|---|---| +| libsecp256k1 | https://github.com/bitcoin-core/secp256k1 | `7fecac74aed8e1fd9078380d67dd04663705c989` | +| RandomX | https://github.com/tevador/RandomX | `1e9d4b2df63fa6edf46b06789486e23c0fcaa55a` | + +When updating either dependency, rebuild from a clean dependency directory and +run the full selftest suite before opening the PR. The PR should explain why the +dependency changed and whether the update can affect consensus, addresses, +signatures, proof-of-work validation, or mining. -- cgit v1.2.3 From b3a5a858e536acf65e6c6761293626628f2227bf Mon Sep 17 00:00:00 2001 From: mtg0001 <106211915+mtg0001@users.noreply.github.com> Date: Tue, 4 Aug 2026 15:31:55 -0300 Subject: fuzz: add P2P message parser harness (#142) * fuzz: add P2P message parser harness * fuzz: avoid duplicate legacy header includes * fuzz: seed the corpus with our network magic, not Bitcoin's The two seed inputs began f5 be b6 d9, which is Bitcoin's message start. Ours is bf 20 5c fd. CMessageHeader::IsValid rejects on that field first, so both seeds died at the first check and the smoke run exercised the reject path and nothing else. libFuzzer would have to mutate its way onto four exact bytes before reaching any parser, which does not happen in 128 runs. The job would have gone green while covering none of what it was added to cover. --------- Co-authored-by: Gilcimar Duarte Co-authored-by: Bitflash-sh --- .github/workflows/ci.yml | 3 +++ Makefile | 7 +++++-- src/Makefile | 34 +++++++++++++++++++++++++++++++++- src/fuzz_net_message.cpp | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/fuzz_net_message.cpp (limited to 'Makefile') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 985ba8a..9efd66f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,9 @@ jobs: - name: Run Linux selftests run: make tests + - name: Run P2P message fuzz smoke + run: make fuzz-net-message-smoke + windows-ucrt64: name: Windows UCRT64 selftests runs-on: windows-latest diff --git a/Makefile b/Makefile index 0788b61..736f5d8 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ deps-apt: @if command -v apt-get >/dev/null 2>&1; then \ $(SUDO) apt-get install -y build-essential cmake git pkg-config autoconf \ libtool libssl-dev libdb5.3++-dev libsodium-dev nlohmann-json3-dev \ - libboost-system-dev libglfw3-dev libgl-dev python3-pil; \ + libboost-system-dev libglfw3-dev libgl-dev python3-pil clang; \ else \ echo "Not an apt system — install: g++ cmake git autoconf libtool"; \ echo " libssl libdb++ libsodium nlohmann-json boost glfw3 opengl python3-pil"; \ @@ -191,6 +191,9 @@ clean: tests: $(MAKE) -C src -f Makefile tests +fuzz-net-message-smoke: deps-linux + $(MAKE) -C src -f Makefile fuzz-net-message-smoke + checksums: ./scripts/make-release-checksums.sh @@ -201,5 +204,5 @@ verify-release: ./scripts/verify-release.sh $(if $(TAG),$(TAG),latest) .PHONY: linux windows clean appimage \ - tests checksums sign-checksums verify-release \ + tests fuzz-net-message-smoke checksums sign-checksums verify-release \ deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx diff --git a/src/Makefile b/src/Makefile index 3577dd6..ac0226e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,6 +2,7 @@ # Called by: make linux (root Makefile) CXX ?= g++ +FUZZ_CXX ?= clang++ SECP_INC ?= /usr/local/include SECP_LIB ?= /usr/local/lib @@ -33,6 +34,9 @@ CXXFLAGS = -std=gnu++14 -O2 $(WARNFLAGS) -fpermissive -pthread \ -I$(SECP_INC) -I$(RANDOMX_DIR)/src \ -I/usr/include/nlohmann \ -I$(IMGUI_DIR) +FUZZ_CXXFLAGS = $(filter-out -O2,$(CXXFLAGS)) -O1 -g -fno-omit-frame-pointer \ + -fsanitize=fuzzer-no-link,address,undefined +FUZZ_LDFLAGS = -fsanitize=fuzzer,address,undefined LIBS = -L$(SECP_LIB) -lsecp256k1 \ -L$(RANDOMX_DIR)/build -lrandomx \ @@ -117,6 +121,9 @@ NODE_LIBS = -L$(SECP_LIB) -lsecp256k1 \ NODE_ONLY_OBJS = $(patsubst obj/%,obj-node/%,$(NODE_OBJS)) \ obj-node/main_gui.o obj-node/headless.o +FUZZ_OBJS = $(patsubst obj/%,obj-fuzz/%,$(NODE_OBJS)) \ + obj-fuzz/fuzz_net_message.o + obj-node/%.o: %.cpp $(HEADERS) @mkdir -p obj-node $(CXX) -c $(CXXFLAGS) -DBITFLASH_NO_GUI -o $@ $< @@ -129,8 +136,31 @@ bitflash-node: $(NODE_ONLY_OBJS) $(CXX) $(CXXFLAGS) -o $@ $^ $(NODE_LIBS) @echo "Built: bitflash-node (headless, no libGL needed)" +obj-fuzz/%.o: %.cpp $(HEADERS) + @mkdir -p obj-fuzz + $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -o $@ $< + +obj-fuzz/sha.o: sha.cpp sha.h + @mkdir -p obj-fuzz + $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -O1 -o $@ $< + +obj-fuzz/fuzz_net_message.o: fuzz_net_message.cpp $(HEADERS) + @mkdir -p obj-fuzz + $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -o $@ $< + +fuzz-net-message: $(FUZZ_OBJS) + $(FUZZ_CXX) $(filter-out -fsanitize=fuzzer-no-link%,$(FUZZ_CXXFLAGS)) \ + $(FUZZ_LDFLAGS) -o $@ $^ $(NODE_LIBS) + @echo "Built: fuzz-net-message" + +fuzz-net-message-smoke: fuzz-net-message + @mkdir -p ../work/fuzz-corpus/net-message + @printf '\277\040\134\375ping\000\000\000\000\000\000\000\000\000\000\000\000' > ../work/fuzz-corpus/net-message/ping-header + @printf '\277\040\134\375version\000\000\000\000\000\000\000\000\000' > ../work/fuzz-corpus/net-message/version-header + ./fuzz-net-message -runs=128 ../work/fuzz-corpus/net-message + clean: - rm -rf obj obj-node bitflash bitflash-node test_bip32 + rm -rf obj obj-node obj-fuzz bitflash bitflash-node fuzz-net-message test_bip32 test_bip32: test_bip32.cpp bip32.cpp bip32.h bip39_english.h $(CXX) $(CXXFLAGS) -o $@ test_bip32.cpp bip32.cpp -lssl -lcrypto @@ -144,3 +174,5 @@ tests: test_bip32 bitflash-node ./bitflash-node -selftest=wallet-encrypt ./bitflash-node -selftest=net-message ./bitflash-node -selftest=consensus-limits + +.PHONY: tests fuzz-net-message-smoke diff --git a/src/fuzz_net_message.cpp b/src/fuzz_net_message.cpp new file mode 100644 index 0000000..1104d90 --- /dev/null +++ b/src/fuzz_net_message.cpp @@ -0,0 +1,32 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. +// +// libFuzzer harness for the P2P message envelope parser. It feeds arbitrary +// receive-buffer bytes into ProcessMessages() through a dummy CNode, without +// opening sockets or starting node threads. + +#include "headers_core.h" + +#include +#include + +// Stand-ins normally supplied by the GUI/headless entry objects. +map mapAddressBook; +bool gPoolServerRunning = false; +void MainFrameRepaint() {} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + // Keep this first target focused on parser behavior, not multi-megabyte + // allocation pressure. The protocol size guards have their own selftest. + if (size > 4096) + return 0; + + CNode node(INVALID_SOCKET, CAddress("127.0.0.1")); + node.nVersion = 0; // exercise pre-version gating plus the version parser + if (size > 0) + node.vRecv.write((const char*)data, (int)size); + + ProcessMessages(&node); + return 0; +} -- cgit v1.2.3 From 4de5cca7e7a0a7104dae8d414add33f6e9562e4a Mon Sep 17 00:00:00 2001 From: Nsable-sh Date: Fri, 7 Aug 2026 10:55:54 -0300 Subject: fuzz: add script parser harness (#5) --- .github/workflows/ci.yml | 3 +++ Makefile | 5 +++- src/Makefile | 27 ++++++++++++++++++---- src/fuzz_script.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 src/fuzz_script.cpp (limited to 'Makefile') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9efd66f..ba8074c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,9 @@ jobs: - name: Run P2P message fuzz smoke run: make fuzz-net-message-smoke + - name: Run script fuzz smoke + run: make fuzz-script-smoke + windows-ucrt64: name: Windows UCRT64 selftests runs-on: windows-latest diff --git a/Makefile b/Makefile index 736f5d8..d0f1b26 100644 --- a/Makefile +++ b/Makefile @@ -194,6 +194,9 @@ tests: fuzz-net-message-smoke: deps-linux $(MAKE) -C src -f Makefile fuzz-net-message-smoke +fuzz-script-smoke: deps-linux + $(MAKE) -C src -f Makefile fuzz-script-smoke + checksums: ./scripts/make-release-checksums.sh @@ -204,5 +207,5 @@ verify-release: ./scripts/verify-release.sh $(if $(TAG),$(TAG),latest) .PHONY: linux windows clean appimage \ - tests fuzz-net-message-smoke checksums sign-checksums verify-release \ + tests fuzz-net-message-smoke fuzz-script-smoke checksums sign-checksums verify-release \ deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx diff --git a/src/Makefile b/src/Makefile index ac0226e..cc52fd6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -121,8 +121,9 @@ NODE_LIBS = -L$(SECP_LIB) -lsecp256k1 \ NODE_ONLY_OBJS = $(patsubst obj/%,obj-node/%,$(NODE_OBJS)) \ obj-node/main_gui.o obj-node/headless.o -FUZZ_OBJS = $(patsubst obj/%,obj-fuzz/%,$(NODE_OBJS)) \ - obj-fuzz/fuzz_net_message.o +FUZZ_BASE_OBJS = $(patsubst obj/%,obj-fuzz/%,$(NODE_OBJS)) +FUZZ_NET_MESSAGE_OBJS = $(FUZZ_BASE_OBJS) obj-fuzz/fuzz_net_message.o +FUZZ_SCRIPT_OBJS = $(FUZZ_BASE_OBJS) obj-fuzz/fuzz_script.o obj-node/%.o: %.cpp $(HEADERS) @mkdir -p obj-node @@ -148,19 +149,35 @@ obj-fuzz/fuzz_net_message.o: fuzz_net_message.cpp $(HEADERS) @mkdir -p obj-fuzz $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -o $@ $< -fuzz-net-message: $(FUZZ_OBJS) +obj-fuzz/fuzz_script.o: fuzz_script.cpp $(HEADERS) + @mkdir -p obj-fuzz + $(FUZZ_CXX) -c $(FUZZ_CXXFLAGS) -DBITFLASH_FUZZ -o $@ $< + +fuzz-net-message: $(FUZZ_NET_MESSAGE_OBJS) $(FUZZ_CXX) $(filter-out -fsanitize=fuzzer-no-link%,$(FUZZ_CXXFLAGS)) \ $(FUZZ_LDFLAGS) -o $@ $^ $(NODE_LIBS) @echo "Built: fuzz-net-message" +fuzz-script: $(FUZZ_SCRIPT_OBJS) + $(FUZZ_CXX) $(filter-out -fsanitize=fuzzer-no-link%,$(FUZZ_CXXFLAGS)) \ + $(FUZZ_LDFLAGS) -o $@ $^ $(NODE_LIBS) + @echo "Built: fuzz-script" + fuzz-net-message-smoke: fuzz-net-message @mkdir -p ../work/fuzz-corpus/net-message @printf '\277\040\134\375ping\000\000\000\000\000\000\000\000\000\000\000\000' > ../work/fuzz-corpus/net-message/ping-header @printf '\277\040\134\375version\000\000\000\000\000\000\000\000\000' > ../work/fuzz-corpus/net-message/version-header ./fuzz-net-message -runs=128 ../work/fuzz-corpus/net-message +fuzz-script-smoke: fuzz-script + @mkdir -p ../work/fuzz-corpus/script + @printf '\000\121' > ../work/fuzz-corpus/script/op-true + @printf '\001\166\251\024\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\210\254' > ../work/fuzz-corpus/script/p2pkh-shape + @printf '\000\115\377\377' > ../work/fuzz-corpus/script/truncated-pushdata2 + ./fuzz-script -runs=128 ../work/fuzz-corpus/script + clean: - rm -rf obj obj-node obj-fuzz bitflash bitflash-node fuzz-net-message test_bip32 + rm -rf obj obj-node obj-fuzz bitflash bitflash-node fuzz-net-message fuzz-script test_bip32 test_bip32: test_bip32.cpp bip32.cpp bip32.h bip39_english.h $(CXX) $(CXXFLAGS) -o $@ test_bip32.cpp bip32.cpp -lssl -lcrypto @@ -175,4 +192,4 @@ tests: test_bip32 bitflash-node ./bitflash-node -selftest=net-message ./bitflash-node -selftest=consensus-limits -.PHONY: tests fuzz-net-message-smoke +.PHONY: tests fuzz-net-message-smoke fuzz-script-smoke diff --git a/src/fuzz_script.cpp b/src/fuzz_script.cpp new file mode 100644 index 0000000..28c84f6 --- /dev/null +++ b/src/fuzz_script.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. +// +// libFuzzer harness for raw script parsing and evaluation. It keeps the +// target deliberately small: arbitrary bytes become one CScript, then the +// parser, standard-script extractors and EvalScript all see that same input. + +#include "headers_core.h" + +#include +#include + +// Stand-ins normally supplied by the GUI/headless entry objects. +map mapAddressBook; +bool gPoolServerRunning = false; +void MainFrameRepaint() {} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + if (size < 1 || size > 4096) + return 0; + + try + { + int nHashType = data[0]; + const unsigned char* pbegin = data + 1; + const unsigned char* pend = data + size; + CScript script(pbegin, pend); + + CScript::const_iterator pc = script.begin(); + opcodetype opcode; + vector vchPush; + while (pc < script.end()) + { + if (!script.GetOp(pc, opcode, vchPush)) + break; + } + + script.GetSigOpCount(); + script.ToString(); + + vector vchPubKey; + ExtractPubKey(script, false, vchPubKey); + uint160 hash160; + ExtractHash160(script, hash160); + + CTransaction tx; + tx.vin.push_back(CTxIn(COutPoint(), CScript())); + tx.vout.push_back(CTxOut(0, CScript())); + + vector > stack; + EvalScript(script, tx, 0, nHashType, &stack); + } + catch (...) + { + } + + return 0; +} -- cgit v1.2.3 From dfab2226330ccf5b6529a0e7355e1f574526de94 Mon Sep 17 00:00:00 2001 From: Bitflash Date: Mon, 10 Aug 2026 09:43:27 -0300 Subject: release: bump version to 1.2.16 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index d0f1b26..1d9965a 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.15 +VERSION := 1.2.16 SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1 SECP256K1_COMMIT := 7fecac74aed8e1fd9078380d67dd04663705c989 -- cgit v1.2.3 From 0d125b59899258400ad3ffa73e1efb80e9fcf81a Mon Sep 17 00:00:00 2001 From: bitflash Date: Wed, 12 Aug 2026 09:09:03 -0300 Subject: release: bump version to 1.2.17 (hardened audit tooling) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 1d9965a..6cea1a8 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.16 +VERSION := 1.2.17 SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1 SECP256K1_COMMIT := 7fecac74aed8e1fd9078380d67dd04663705c989 -- cgit v1.2.3 From bc3de301d9ed0e5fb5e2034be2e066d77cf23804 Mon Sep 17 00:00:00 2001 From: bitflash Date: Wed, 12 Aug 2026 10:36:49 -0300 Subject: release: v1.2.18 (Tor/SOCKS5 outbound privacy, poll() socket handler, new app icon) --- Makefile | 2 +- src/rc/bitcoin.ico | Bin 372526 -> 150897 bytes 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 6cea1a8..b4d0cf7 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.17 +VERSION := 1.2.18 SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1 SECP256K1_COMMIT := 7fecac74aed8e1fd9078380d67dd04663705c989 diff --git a/src/rc/bitcoin.ico b/src/rc/bitcoin.ico index b768077..33323de 100644 Binary files a/src/rc/bitcoin.ico and b/src/rc/bitcoin.ico differ -- cgit v1.2.3 From 44fbf6895bd3acd11f552514e746a2e3876cad2d Mon Sep 17 00:00:00 2001 From: Nsable-sh Date: Thu, 13 Aug 2026 14:29:14 -0300 Subject: release: package Windows builds with managed Tor --- Makefile | 6 +- README.md | 13 ++++ docs/release-verification.md | 6 ++ docs/tor.md | 16 +++++ scripts/make-release-checksums.sh | 2 + scripts/package-windows-tor.sh | 132 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100755 scripts/package-windows-tor.sh (limited to 'Makefile') diff --git a/Makefile b/Makefile index b4d0cf7..d1277a4 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ # # make linux build Bitflash-*-x86_64.AppImage # make windows build Bitflash-*-windows.zip (from MSYS2 UCRT64) +# make windows-tor build Bitflash-*-windows-with-tor.zip # make tests build and run standalone unit tests # make checksums create SHA256SUMS for release assets # make verify-release TAG=v1.2.13 @@ -180,6 +181,9 @@ windows: deps-windows @zip -r Bitflash-$(VERSION)-windows.zip Bitflash-$(VERSION)-windows/ @echo "Built: Bitflash-$(VERSION)-windows.zip" +windows-tor: windows + ./scripts/package-windows-tor.sh + # ---- Clean ---------------------------------------------------------------- clean: @@ -206,6 +210,6 @@ sign-checksums: verify-release: ./scripts/verify-release.sh $(if $(TAG),$(TAG),latest) -.PHONY: linux windows clean appimage \ +.PHONY: linux windows windows-tor clean appimage \ tests fuzz-net-message-smoke fuzz-script-smoke checksums sign-checksums verify-release \ deps-linux deps-windows deps-apt deps-secp256k1 deps-randomx diff --git a/README.md b/README.md index a7ce2b2..c30f171 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ configuration — it connects automatically and starts syncing. **Linux:** make the `.AppImage` executable and run it. **Windows:** extract the `-windows.zip` and run `Bitflash.exe`. +If you want managed Tor without a separate Tor install, use the +`-windows-with-tor.zip` package and start Bitflash with `-managedtor`. Every release ships a `SHA256SUMS` covering the assets. Verifying takes a second and is worth doing: @@ -452,6 +454,17 @@ make windows ``` Installs deps via pacman, produces `Bitflash-*-windows.zip`. +To build the Windows package that also carries the Tor Expert Bundle: + +```bash +make windows-tor +``` + +That produces `Bitflash-*-windows-with-tor.zip`. The release script downloads +the Tor Expert Bundle from the official Tor archive, verifies its pinned SHA256, +and places `tor/tor.exe` beside `Bitflash.exe` so `-managedtor` works without a +separate Tor install. + --- ## At a glance diff --git a/docs/release-verification.md b/docs/release-verification.md index 408bab9..04d18a3 100644 --- a/docs/release-verification.md +++ b/docs/release-verification.md @@ -81,6 +81,12 @@ Publish, alongside the assets, `SHA256SUMS` and `SHA256SUMS.asc`, and update is ever rotated, announce the new fingerprint clearly and update the embedded key in `verify-release.sh`. +For Windows releases with managed Tor built in, run `make windows-tor`. It +creates `Bitflash-*-windows-with-tor.zip` by downloading the Tor Expert Bundle, +checking the pinned SHA256 in `scripts/package-windows-tor.sh`, and placing +`tor/tor.exe` next to `Bitflash.exe`. Include that zip in `SHA256SUMS` like any +other release asset. + ## Why this matters `SHA256SUMS` alone protects against a broken download, but not against someone diff --git a/docs/tor.md b/docs/tor.md index 1c0f589..be6a145 100644 --- a/docs/tor.md +++ b/docs/tor.md @@ -53,6 +53,22 @@ Without a value, Bitflash looks for Tor in this order: 2. `tor.exe` or `tor` beside the Bitflash binary; 3. `tor.exe` or `tor` on `PATH`. +Windows releases can also be built as `Bitflash-*-windows-with-tor.zip`. That +package includes the official Tor Expert Bundle under `tor/`, so the first path +above exists immediately after extraction and `bitflash -managedtor` needs no +separate Tor install. + +The bundled-Tor package is created by: + +```bash +make windows-tor +``` + +The packaging script verifies a pinned SHA256 for the downloaded Tor Expert +Bundle before copying it into the release directory. The Tor binary is bundled; +the runtime data directory, hidden-service key, and control cookie are still +created under the user's Bitflash data directory. + To point at a specific Tor executable: ```bash diff --git a/scripts/make-release-checksums.sh b/scripts/make-release-checksums.sh index 5b29e2d..9c4f45a 100755 --- a/scripts/make-release-checksums.sh +++ b/scripts/make-release-checksums.sh @@ -10,6 +10,7 @@ Usage: scripts/make-release-checksums.sh [--sign] [--local-user KEYID] Creates SHA256SUMS for release assets in the current directory: Bitflash-*-windows.zip + Bitflash-*-windows-with-tor.zip Bitflash-*-x86_64.AppImage bitflash-node-*-x86_64 @@ -44,6 +45,7 @@ fi assets=() for pattern in \ "Bitflash-*-windows.zip" \ + "Bitflash-*-windows-with-tor.zip" \ "Bitflash-*-x86_64.AppImage" \ "bitflash-node-*-x86_64" do diff --git a/scripts/package-windows-tor.sh b/scripts/package-windows-tor.sh new file mode 100755 index 0000000..084fd1a --- /dev/null +++ b/scripts/package-windows-tor.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +VERSION="${VERSION:-$(sed -n 's/^VERSION[[:space:]]*:= *//p' "$ROOT/Makefile" | head -1)}" + +TOR_VERSION="${TOR_VERSION:-15.0.19}" +TOR_ARCHIVE_NAME="tor-expert-bundle-windows-x86_64-${TOR_VERSION}.tar.gz" +TOR_URL="${TOR_URL:-https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/${TOR_ARCHIVE_NAME}}" +TOR_SHA256="${TOR_SHA256:-6AC067402C7B4A3DC37887ED3754B3914B67FDC220C966190683E9CCF91ABF0F}" + +BUNDLE_DIR="${BUNDLE_DIR:-$ROOT/Bitflash-${VERSION}-windows}" +OUT_ZIP="${OUT_ZIP:-$ROOT/Bitflash-${VERSION}-windows-with-tor.zip}" +CACHE_DIR="${CACHE_DIR:-$ROOT/.cache}" +ARCHIVE="${TOR_ARCHIVE:-$CACHE_DIR/$TOR_ARCHIVE_NAME}" + +usage() { + cat </dev/null 2>&1 || { + echo "missing required command: $1" >&2 + exit 1 + } +} + +need sha256sum +need tar +need zip + +if [ ! -d "$BUNDLE_DIR" ]; then + echo "missing Windows release directory: $BUNDLE_DIR" >&2 + echo "run 'make windows' first, or set BUNDLE_DIR" >&2 + exit 1 +fi +if [ ! -f "$BUNDLE_DIR/Bitflash.exe" ]; then + echo "missing Bitflash.exe in $BUNDLE_DIR" >&2 + exit 1 +fi +BUNDLE_PARENT="$(cd "$(dirname "$BUNDLE_DIR")" && pwd)" +BUNDLE_NAME="$(basename "$BUNDLE_DIR")" +OUT_PARENT="$(mkdir -p "$(dirname "$OUT_ZIP")" && cd "$(dirname "$OUT_ZIP")" && pwd)" +OUT_NAME="$(basename "$OUT_ZIP")" +OUT_ZIP_ABS="$OUT_PARENT/$OUT_NAME" + +mkdir -p "$CACHE_DIR" +if [ ! -f "$ARCHIVE" ]; then + if command -v curl >/dev/null 2>&1; then + curl -L --fail --output "$ARCHIVE" "$TOR_URL" + elif command -v wget >/dev/null 2>&1; then + wget -O "$ARCHIVE" "$TOR_URL" + else + echo "missing required command: curl or wget" >&2 + exit 1 + fi +fi + +got="$(sha256sum "$ARCHIVE" | awk '{print tolower($1)}')" +want="$(printf '%s' "$TOR_SHA256" | tr 'A-F' 'a-f')" +if [ "$got" != "$want" ]; then + echo "Tor archive SHA256 mismatch" >&2 + echo " expected: $want" >&2 + echo " got: $got" >&2 + exit 1 +fi + +tmp="$(mktemp -d "${TMPDIR:-/tmp}/bitflash-tor-package.XXXXXX")" +trap 'rm -rf "$tmp"' EXIT + +mkdir -p "$tmp/extract" +tar -xzf "$ARCHIVE" -C "$tmp/extract" + +if [ ! -f "$tmp/extract/tor/tor.exe" ]; then + echo "Tor archive did not contain tor/tor.exe" >&2 + exit 1 +fi + +rm -rf "$BUNDLE_DIR/tor" +mkdir -p "$BUNDLE_DIR/tor" +cp -R "$tmp/extract/tor/." "$BUNDLE_DIR/tor/" +if [ -d "$tmp/extract/docs" ]; then + mkdir -p "$BUNDLE_DIR/tor/docs" + cp -R "$tmp/extract/docs/." "$BUNDLE_DIR/tor/docs/" +fi +if [ -d "$tmp/extract/data" ]; then + mkdir -p "$BUNDLE_DIR/tor/data-defaults" + cp -R "$tmp/extract/data/." "$BUNDLE_DIR/tor/data-defaults/" +fi + +cat > "$BUNDLE_DIR/TOR-EXPERT-BUNDLE.txt" < Date: Thu, 13 Aug 2026 16:56:01 -0300 Subject: release: v1.2.19 (nHDNext restore fix, Tor onion transport: managed Tor, direct onion peers, onion-only mode) --- Makefile | 2 +- README.md | 2 +- build-1219.log | 381 ++++++++++++++++++++ build-17.log | 78 +++++ build-appimage.log | 5 + build-node.log | 387 +++++++++++++++++++++ docs/site.md | 4 +- scripts/__pycache__/bitflash_chain.cpython-313.pyc | Bin 0 -> 22668 bytes 8 files changed, 855 insertions(+), 4 deletions(-) create mode 100644 build-1219.log create mode 100644 build-17.log create mode 100644 build-appimage.log create mode 100644 build-node.log create mode 100644 scripts/__pycache__/bitflash_chain.cpython-313.pyc (limited to 'Makefile') diff --git a/Makefile b/Makefile index d1277a4..60d1227 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.18 +VERSION := 1.2.19 SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1 SECP256K1_COMMIT := 7fecac74aed8e1fd9078380d67dd04663705c989 diff --git a/README.md b/README.md index bb6a4d4..1782bc3 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Public mirrors should make the latest checksum files available both under the versioned release directory and at the release root: ```text -https://releases.bitflash.network/v1.2.18/SHA256SUMS +https://releases.bitflash.network/v1.2.19/SHA256SUMS https://releases.bitflash.network/SHA256SUMS # alias to latest ``` diff --git a/build-1219.log b/build-1219.log new file mode 100644 index 0000000..9aa1b25 --- /dev/null +++ b/build-1219.log @@ -0,0 +1,381 @@ +Lendo listas de pacotes... +Construindo árvore de dependências... +Lendo informação de estado... +build-essential já é a versão mais nova (12.12). +cmake já é a versão mais nova (3.31.6-2). +git já é a versão mais nova (1:2.47.3-0+deb13u1). +pkg-config já é a versão mais nova (1.8.1-4). +autoconf já é a versão mais nova (2.72-3.1). +libtool já é a versão mais nova (2.5.4-4). +libssl-dev já é a versão mais nova (3.5.6-1~deb13u2). +libdb5.3++-dev já é a versão mais nova (5.3.28+dfsg2-9). +libsodium-dev já é a versão mais nova (1.0.18-1+deb13u1). +nlohmann-json3-dev já é a versão mais nova (3.11.3-2.1). +libboost-system-dev já é a versão mais nova (1.83.0.2+b2). +libglfw3-dev já é a versão mais nova (3.4-3). +libgl-dev já é a versão mais nova (1.7.0-1+b2). +python3-pil já é a versão mais nova (11.1.0-5+deb13u4). +clang já é a versão mais nova (1:19.0-63). +0 pacotes atualizados, 0 pacotes novos instalados, 0 a serem removidos e 44 não atualizados. +==> building libsecp256k1 +==> libsecp256k1 pinned at 7fecac74aed8e1fd9078380d67dd04663705c989 +libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, 'autotools-aux'. +libtoolize: copying file 'autotools-aux/ltmain.sh' +libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'autotools-aux/m4'. +libtoolize: copying file 'autotools-aux/m4/libtool.m4' +libtoolize: copying file 'autotools-aux/m4/ltoptions.m4' +libtoolize: copying file 'autotools-aux/m4/ltsugar.m4' +libtoolize: copying file 'autotools-aux/m4/ltversion.m4' +libtoolize: copying file 'autotools-aux/m4/lt~obsolete.m4' +configure.ac:39: installing 'autotools-aux/ar-lib' +configure.ac:37: installing 'autotools-aux/compile' +configure.ac:24: installing 'autotools-aux/config.guess' +configure.ac:24: installing 'autotools-aux/config.sub' +configure.ac:27: installing 'autotools-aux/install-sh' +configure.ac:27: installing 'autotools-aux/missing' +Makefile.am: installing 'autotools-aux/depcomp' +parallel-tests: installing 'autotools-aux/test-driver' +checking build system type... x86_64-pc-linux-gnu +checking host system type... x86_64-pc-linux-gnu +checking for a BSD-compatible install... /usr/bin/install -c +checking whether sleep supports fractional seconds... yes +checking filesystem timestamp resolution... 0.01 +checking whether build environment is sane... yes +checking for a race-free mkdir -p... /usr/bin/mkdir -p +checking for gawk... no +checking for mawk... mawk +checking whether make sets $(MAKE)... yes +checking whether make supports nested variables... yes +checking xargs -n works... yes +checking for gcc... gcc +checking whether the C compiler works... yes +checking for C compiler default output file name... a.out +checking for suffix of executables... +checking whether we are cross compiling... no +checking for suffix of object files... o +checking whether the compiler supports GNU C... yes +checking whether gcc accepts -g... yes +checking for gcc option to enable C11 features... none needed +checking whether gcc understands -c and -o together... yes +checking whether make supports the include directive... yes (GNU style) +checking dependency style of gcc... gcc3 +checking dependency style of gcc... gcc3 +checking for ar... ar +checking the archiver (ar) interface... ar +checking how to print strings... printf +checking for a sed that does not truncate output... /usr/bin/sed +checking for grep that handles long lines and -e... /usr/bin/grep +checking for egrep... /usr/bin/grep -E +checking for fgrep... /usr/bin/grep -F +checking for ld used by gcc... /usr/bin/ld +checking if the linker (/usr/bin/ld) is GNU ld... yes +checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B +checking the name lister (/usr/bin/nm -B) interface... BSD nm +checking whether ln -s works... yes +checking the maximum length of command line arguments... 1572864 +checking how to convert x86_64-pc-linux-gnu file names to x86_64-pc-linux-gnu format... func_convert_file_noop +checking how to convert x86_64-pc-linux-gnu file names to toolchain format... func_convert_file_noop +checking for /usr/bin/ld option to reload object files... -r +checking for file... file +checking for objdump... objdump +checking how to recognize dependent libraries... pass_all +checking for dlltool... no +checking how to associate runtime and link libraries... printf %s\n +checking for ranlib... ranlib +checking for archiver @FILE support... @ +checking for strip... strip +checking command to parse /usr/bin/nm -B output from gcc object... ok +checking for sysroot... no +checking for a working dd... /usr/bin/dd +checking how to truncate binary pipes... /usr/bin/dd bs=4096 count=1 +checking for mt... mt +checking if mt is a manifest tool... no +checking for stdio.h... yes +checking for stdlib.h... yes +checking for string.h... yes +checking for inttypes.h... yes +checking for stdint.h... yes +checking for strings.h... yes +checking for sys/stat.h... yes +checking for sys/types.h... yes +checking for unistd.h... yes +checking for dlfcn.h... yes +checking for objdir... .libs +checking if gcc supports -fno-rtti -fno-exceptions... no +checking for gcc option to produce PIC... -fPIC -DPIC +checking if gcc PIC flag -fPIC -DPIC works... yes +checking if gcc static flag -static works... yes +checking if gcc supports -c -o file.o... yes +checking if gcc supports -c -o file.o... (cached) yes +checking whether the gcc linker (/usr/bin/ld -m elf_x86_64) supports shared libraries... yes +checking dynamic linker characteristics... GNU/Linux ld.so +checking how to hardcode library paths into programs... immediate +checking whether stripping libraries is possible... yes +checking if libtool supports shared libraries... yes +checking whether to build shared libraries... no +checking whether to build static libraries... yes +checking if gcc supports -Werror... yes +checking if gcc supports -std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef... yes +checking if gcc supports -Wno-overlength-strings... yes +checking if gcc supports -Wall... yes +checking if gcc supports -Wno-unused-function... yes +checking if gcc supports -Wextra... yes +checking if gcc supports -Wcast-align... yes +checking if gcc supports -Wcast-align=strict... yes +checking if gcc supports -Wconditional-uninitialized... no +checking if gcc supports -Wreserved-identifier... no +checking if gcc supports -Wtrailing-whitespace=any... no +checking if gcc supports -Wleading-whitespace=spaces... no +checking for valgrind support... +checking for x86_64 assembly availability... yes +checking that generated files are newer than configure... done +configure: creating ./config.status +config.status: creating Makefile +config.status: creating libsecp256k1.pc +config.status: executing depfiles commands +config.status: executing libtool commands + +Build Options: + with external callbacks = no + with benchmarks = no + with tests = no + with exhaustive tests = yes + with ctime tests = no + with coverage = no + with examples = no + module ecdh = yes + module recovery = no + module extrakeys = yes + module schnorrsig = yes + module musig = yes + module ellswift = yes + module silentpayments = yes + + asm = x86_64 + ecmult window size = 15 + ecmult gen table size = 86 KiB + + valgrind = no + CC = gcc + CPPFLAGS = + SECP_CFLAGS = -O2 -std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef -Wno-overlength-strings -Wall -Wno-unused-function -Wextra -Wcast-align -Wcast-align=strict + CFLAGS = -g -O2 + LDFLAGS = +make[1]: Entrando no diretório '/root/rel16/secp256k1-build' + +make all-am +make[2]: Entrando no diretório '/root/rel16/secp256k1-build' + + CC src/exhaustive_tests-tests_exhaustive.o + CCLD exhaustive_tests + CC src/libsecp256k1_la-secp256k1.lo + CC src/libsecp256k1_precomputed_la-precomputed_ecmult.lo + CC src/libsecp256k1_precomputed_la-precomputed_ecmult_gen.lo + CCLD libsecp256k1_precomputed.la + CCLD libsecp256k1.la +make[2]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[1]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[1]: Entrando no diretório '/root/rel16/secp256k1-build' + +make install-am +make[2]: Entrando no diretório '/root/rel16/secp256k1-build' + +make[3]: Entrando no diretório '/root/rel16/secp256k1-build' + + /usr/bin/mkdir -p '/usr/local/lib' + /bin/bash ./libtool --mode=install /usr/bin/install -c libsecp256k1.la '/usr/local/lib' +libtool: install: /usr/bin/install -c .libs/libsecp256k1.lai /usr/local/lib/libsecp256k1.la +libtool: install: /usr/bin/install -c .libs/libsecp256k1.a /usr/local/lib/libsecp256k1.a +libtool: install: chmod 644 /usr/local/lib/libsecp256k1.a +libtool: install: ranlib /usr/local/lib/libsecp256k1.a +libtool: finish: PATH="/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin" ldconfig -n /usr/local/lib +---------------------------------------------------------------------- +Libraries have been installed in: + /usr/local/lib + +If you ever happen to want to link against installed libraries +in a given directory, LIBDIR, you must either use libtool, and +specify the full pathname of the library, or use the '-LLIBDIR' +flag during linking and do at least one of the following: + - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable + during execution + - add LIBDIR to the 'LD_RUN_PATH' environment variable + during linking + - use the '-Wl,-rpath -Wl,LIBDIR' linker flag + - have your system administrator add LIBDIR to '/etc/ld.so.conf' + +See any operating system documentation about shared libraries for +more information, such as the ld(1) and ld.so(8) manual pages. +---------------------------------------------------------------------- + /usr/bin/mkdir -p '/usr/local/include' + /usr/bin/install -c -m 644 include/secp256k1.h include/secp256k1_preallocated.h include/secp256k1_ecdh.h include/secp256k1_extrakeys.h include/secp256k1_schnorrsig.h include/secp256k1_musig.h include/secp256k1_ellswift.h include/secp256k1_silentpayments.h '/usr/local/include' + /usr/bin/mkdir -p '/usr/local/lib/pkgconfig' + /usr/bin/install -c -m 644 libsecp256k1.pc '/usr/local/lib/pkgconfig' +make[3]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[2]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[1]: Saindo do diretório '/root/rel16/secp256k1-build' + +==> libsecp256k1 done +==> building RandomX +==> RandomX pinned at 1e9d4b2df63fa6edf46b06789486e23c0fcaa55a +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /usr/bin/cc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /usr/bin/c++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Performing Test _maes_cxx +-- Performing Test _maes_cxx - Success +-- Setting CXX flag -maes +-- Performing Test _maes_c +-- Performing Test _maes_c - Success +-- Setting C flag -maes +-- Performing Test HAVE_SSSE3 +-- Performing Test HAVE_SSSE3 - Success +-- Performing Test HAVE_AVX2 +-- Performing Test HAVE_AVX2 - Success +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success +-- Found Threads: TRUE +-- Performing Test HAVE_CXX_ATOMICS +-- Performing Test HAVE_CXX_ATOMICS - Success +-- Performing Test HAVE_POSIX_MEMALIGN +-- Performing Test HAVE_POSIX_MEMALIGN - Success +-- Configuring done (0.9s) +-- Generating done (0.0s) +-- Build files have been written to: /root/RandomX/build +make[1]: Entrando no diretório '/root/RandomX/build' + +[ 3%] Building CXX object CMakeFiles/randomx.dir/src/aes_hash.cpp.o +[ 7%] Building C object CMakeFiles/randomx.dir/src/argon2_ref.c.o +[ 11%] Building C object CMakeFiles/randomx.dir/src/argon2_ssse3.c.o +[ 14%] Building C object CMakeFiles/randomx.dir/src/argon2_avx2.c.o +[ 18%] Building CXX object CMakeFiles/randomx.dir/src/bytecode_machine.cpp.o +[ 22%] Building CXX object CMakeFiles/randomx.dir/src/cpu.cpp.o +[ 25%] Building CXX object CMakeFiles/randomx.dir/src/dataset.cpp.o +[ 29%] Building CXX object CMakeFiles/randomx.dir/src/soft_aes.cpp.o +[ 33%] Building C object CMakeFiles/randomx.dir/src/virtual_memory.c.o +[ 37%] Building CXX object CMakeFiles/randomx.dir/src/vm_interpreted.cpp.o +[ 40%] Building CXX object CMakeFiles/randomx.dir/src/allocator.cpp.o +[ 44%] Building CXX object CMakeFiles/randomx.dir/src/assembly_generator_x86.cpp.o +[ 48%] Building CXX object CMakeFiles/randomx.dir/src/instruction.cpp.o +[ 51%] Building CXX object CMakeFiles/randomx.dir/src/randomx.cpp.o +[ 55%] Building CXX object CMakeFiles/randomx.dir/src/superscalar.cpp.o +[ 59%] Building CXX object CMakeFiles/randomx.dir/src/vm_compiled.cpp.o +[ 62%] Building CXX object CMakeFiles/randomx.dir/src/vm_interpreted_light.cpp.o +[ 66%] Building C object CMakeFiles/randomx.dir/src/argon2_core.c.o +[ 70%] Building CXX object CMakeFiles/randomx.dir/src/blake2_generator.cpp.o +[ 74%] Building CXX object CMakeFiles/randomx.dir/src/instructions_portable.cpp.o +[ 77%] Building C object CMakeFiles/randomx.dir/src/reciprocal.c.o +[ 81%] Building CXX object CMakeFiles/randomx.dir/src/virtual_machine.cpp.o +[ 85%] Building CXX object CMakeFiles/randomx.dir/src/vm_compiled_light.cpp.o +[ 88%] Building C object CMakeFiles/randomx.dir/src/blake2/blake2b.c.o +[ 92%] Building CXX object CMakeFiles/randomx.dir/src/jit_compiler_x86.cpp.o +[ 96%] Building C object CMakeFiles/randomx.dir/src/jit_compiler_x86_static.S.o +[100%] Linking CXX static library librandomx.a +[100%] Built target randomx +make[1]: Saindo do diretório '/root/RandomX/build' + +==> RandomX done +make -C src -f Makefile -j1 +make[1]: Entrando no diretório '/root/rel16/src' + +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/util.o util.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/script.o script.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/db.o db.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/net.o net.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/main.o main.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/market.o market.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/nostr.o nostr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/randomx_pow.o randomx_pow.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btfaddr.o btfaddr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btfchan.o btfchan.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btfrv.o btfrv.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btftunnel.o btftunnel.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/rpc.o rpc.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/selftest.o selftest.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/bip32.o bip32.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/walletcmd.o walletcmd.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/proxy.o proxy.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/gui.o gui.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/main_gui.o main_gui.cpp +g++ -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o bitflash obj/imgui.o obj/imgui_draw.o obj/imgui_tables.o obj/imgui_widgets.o obj/imgui_impl_glfw.o obj/imgui_impl_opengl3.o obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o obj/sha.o obj/nostr.o obj/randomx_pow.o obj/btfaddr.o obj/btfchan.o obj/btfrv.o obj/btftunnel.o obj/rpc.o obj/selftest.o obj/bip32.o obj/walletcmd.o obj/proxy.o obj/gui.o obj/main_gui.o -L/usr/local/lib -lsecp256k1 -L/root/RandomX/build -lrandomx -lsodium -lssl -lcrypto -ldb_cxx -lpthread -lglfw -lGL +Built: bitflash +make[1]: Saindo do diretório '/root/rel16/src' + +strip src/bitflash +make -f Makefile appimage +make[1]: Entrando no diretório '/root/rel16' + +==> building AppImage + bundled libsodium.so.23 + bundled libdb_cxx-5.3.so + bundled libglfw.so.3 +Built: Bitflash-1.2.19-x86_64.AppImage +make[1]: Saindo do diretório '/root/rel16' + +make -f Makefile linux-node +make[1]: Entrando no diretório '/root/rel16' + +Lendo listas de pacotes... +Construindo árvore de dependências... +Lendo informação de estado... +build-essential já é a versão mais nova (12.12). +cmake já é a versão mais nova (3.31.6-2). +git já é a versão mais nova (1:2.47.3-0+deb13u1). +pkg-config já é a versão mais nova (1.8.1-4). +autoconf já é a versão mais nova (2.72-3.1). +libtool já é a versão mais nova (2.5.4-4). +libssl-dev já é a versão mais nova (3.5.6-1~deb13u2). +libdb5.3++-dev já é a versão mais nova (5.3.28+dfsg2-9). +libsodium-dev já é a versão mais nova (1.0.18-1+deb13u1). +nlohmann-json3-dev já é a versão mais nova (3.11.3-2.1). +libboost-system-dev já é a versão mais nova (1.83.0.2+b2). +libglfw3-dev já é a versão mais nova (3.4-3). +libgl-dev já é a versão mais nova (1.7.0-1+b2). +python3-pil já é a versão mais nova (11.1.0-5+deb13u4). +clang já é a versão mais nova (1:19.0-63). +0 pacotes atualizados, 0 pacotes novos instalados, 0 a serem removidos e 44 não atualizados. +==> libsecp256k1 already installed +==> RandomX already built +make -C src -f Makefile bitflash-node -j1 +make[2]: Entrando no diretório '/root/rel16/src' + +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/util.o util.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/script.o script.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/db.o db.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/net.o net.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/main.o main.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/market.o market.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/nostr.o nostr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/randomx_pow.o randomx_pow.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btfaddr.o btfaddr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btfchan.o btfchan.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btfrv.o btfrv.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btftunnel.o btftunnel.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/rpc.o rpc.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/selftest.o selftest.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/bip32.o bip32.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/walletcmd.o walletcmd.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/proxy.o proxy.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/main_gui.o main_gui.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/headless.o headless.cpp +g++ -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -DBITFLASH_NODE_BUILD -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o bitflash-node obj-node/util.o obj-node/script.o obj-node/db.o obj-node/net.o obj-node/main.o obj-node/market.o obj-node/sha.o obj-node/nostr.o obj-node/randomx_pow.o obj-node/btfaddr.o obj-node/btfchan.o obj-node/btfrv.o obj-node/btftunnel.o obj-node/rpc.o obj-node/selftest.o obj-node/bip32.o obj-node/walletcmd.o obj-node/proxy.o obj-node/main_gui.o obj-node/headless.o -L/usr/local/lib -lsecp256k1 -L/root/RandomX/build -lrandomx -lsodium -lssl -lcrypto -ldb_cxx -lpthread +Built: bitflash-node (headless, no libGL needed) +make[2]: Saindo do diretório '/root/rel16/src' + +strip src/bitflash-node +cp src/bitflash-node bitflash-node-1.2.19-x86_64 +Built: bitflash-node-1.2.19-x86_64 +make[1]: Saindo do diretório '/root/rel16' + diff --git a/build-17.log b/build-17.log new file mode 100644 index 0000000..6c8c841 --- /dev/null +++ b/build-17.log @@ -0,0 +1,78 @@ +Lendo listas de pacotes... +Construindo árvore de dependências... +Lendo informação de estado... +build-essential já é a versão mais nova (12.12). +cmake já é a versão mais nova (3.31.6-2). +git já é a versão mais nova (1:2.47.3-0+deb13u1). +pkg-config já é a versão mais nova (1.8.1-4). +autoconf já é a versão mais nova (2.72-3.1). +libtool já é a versão mais nova (2.5.4-4). +libssl-dev já é a versão mais nova (3.5.6-1~deb13u2). +libdb5.3++-dev já é a versão mais nova (5.3.28+dfsg2-9). +libsodium-dev já é a versão mais nova (1.0.18-1+deb13u1). +nlohmann-json3-dev já é a versão mais nova (3.11.3-2.1). +libboost-system-dev já é a versão mais nova (1.83.0.2+b2). +libglfw3-dev já é a versão mais nova (3.4-3). +libgl-dev já é a versão mais nova (1.7.0-1+b2). +python3-pil já é a versão mais nova (11.1.0-5+deb13u4). +clang já é a versão mais nova (1:19.0-63). +0 pacotes atualizados, 0 pacotes novos instalados, 0 a serem removidos e 49 não atualizados. +==> libsecp256k1 already installed +==> RandomX already built +make -C src -f Makefile -j1 +make[1]: Entrando no diretório '/root/rel16/src' + +make[1]: Nada a ser feito para 'all'. +make[1]: Saindo do diretório '/root/rel16/src' + +strip src/bitflash +make -f Makefile appimage +make[1]: Entrando no diretório '/root/rel16' + +==> building AppImage + bundled libsodium.so.23 + bundled libdb_cxx-5.3.so + bundled libglfw.so.3 +Built: Bitflash-1.2.17-x86_64.AppImage +make[1]: Saindo do diretório '/root/rel16' + +make -f Makefile linux-node +make[1]: Entrando no diretório '/root/rel16' + +Lendo listas de pacotes... +Construindo árvore de dependências... +Lendo informação de estado... +build-essential já é a versão mais nova (12.12). +cmake já é a versão mais nova (3.31.6-2). +git já é a versão mais nova (1:2.47.3-0+deb13u1). +pkg-config já é a versão mais nova (1.8.1-4). +autoconf já é a versão mais nova (2.72-3.1). +libtool já é a versão mais nova (2.5.4-4). +libssl-dev já é a versão mais nova (3.5.6-1~deb13u2). +libdb5.3++-dev já é a versão mais nova (5.3.28+dfsg2-9). +libsodium-dev já é a versão mais nova (1.0.18-1+deb13u1). +nlohmann-json3-dev já é a versão mais nova (3.11.3-2.1). +libboost-system-dev já é a versão mais nova (1.83.0.2+b2). +libglfw3-dev já é a versão mais nova (3.4-3). +libgl-dev já é a versão mais nova (1.7.0-1+b2). +python3-pil já é a versão mais nova (11.1.0-5+deb13u4). +clang já é a versão mais nova (1:19.0-63). +0 pacotes atualizados, 0 pacotes novos instalados, 0 a serem removidos e 49 não atualizados. +==> libsecp256k1 already installed +==> RandomX already built +make -C src -f Makefile bitflash-node -j1 +make[2]: Entrando no diretório '/root/rel16/src' + +make[2]: 'bitflash-node' está atualizado. +make[2]: Saindo do diretório '/root/rel16/src' + +strip src/bitflash-node +cp src/bitflash-node bitflash-node-1.2.17-x86_64 +Built: bitflash-node-1.2.17-x86_64 +make[1]: Saindo do diretório '/root/rel16' + +==> building AppImage + bundled libsodium.so.23 + bundled libdb_cxx-5.3.so + bundled libglfw.so.3 +Built: Bitflash-1.2.17-x86_64.AppImage diff --git a/build-appimage.log b/build-appimage.log new file mode 100644 index 0000000..d6b95ed --- /dev/null +++ b/build-appimage.log @@ -0,0 +1,5 @@ +==> building AppImage + bundled libsodium.so.23 + bundled libdb_cxx-5.3.so + bundled libglfw.so.3 +Built: Bitflash-1.2.16-x86_64.AppImage diff --git a/build-node.log b/build-node.log new file mode 100644 index 0000000..951c2a0 --- /dev/null +++ b/build-node.log @@ -0,0 +1,387 @@ +Lendo listas de pacotes... +Construindo árvore de dependências... +Lendo informação de estado... +build-essential já é a versão mais nova (12.12). +cmake já é a versão mais nova (3.31.6-2). +git já é a versão mais nova (1:2.47.3-0+deb13u1). +pkg-config já é a versão mais nova (1.8.1-4). +autoconf já é a versão mais nova (2.72-3.1). +libtool já é a versão mais nova (2.5.4-4). +libssl-dev já é a versão mais nova (3.5.6-1~deb13u2). +libdb5.3++-dev já é a versão mais nova (5.3.28+dfsg2-9). +libsodium-dev já é a versão mais nova (1.0.18-1+deb13u1). +nlohmann-json3-dev já é a versão mais nova (3.11.3-2.1). +libboost-system-dev já é a versão mais nova (1.83.0.2+b2). +libglfw3-dev já é a versão mais nova (3.4-3). +libgl-dev já é a versão mais nova (1.7.0-1+b2). +python3-pil já é a versão mais nova (11.1.0-5+deb13u4). +clang já é a versão mais nova (1:19.0-63). +0 pacotes atualizados, 0 pacotes novos instalados, 0 a serem removidos e 49 não atualizados. +==> building libsecp256k1 +==> libsecp256k1 pinned at 7fecac74aed8e1fd9078380d67dd04663705c989 +libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, 'autotools-aux'. +libtoolize: copying file 'autotools-aux/ltmain.sh' +libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'autotools-aux/m4'. +libtoolize: copying file 'autotools-aux/m4/libtool.m4' +libtoolize: copying file 'autotools-aux/m4/ltoptions.m4' +libtoolize: copying file 'autotools-aux/m4/ltsugar.m4' +libtoolize: copying file 'autotools-aux/m4/ltversion.m4' +libtoolize: copying file 'autotools-aux/m4/lt~obsolete.m4' +configure.ac:39: installing 'autotools-aux/ar-lib' +configure.ac:37: installing 'autotools-aux/compile' +configure.ac:24: installing 'autotools-aux/config.guess' +configure.ac:24: installing 'autotools-aux/config.sub' +configure.ac:27: installing 'autotools-aux/install-sh' +configure.ac:27: installing 'autotools-aux/missing' +Makefile.am: installing 'autotools-aux/depcomp' +parallel-tests: installing 'autotools-aux/test-driver' +checking build system type... x86_64-pc-linux-gnu +checking host system type... x86_64-pc-linux-gnu +checking for a BSD-compatible install... /usr/bin/install -c +checking whether sleep supports fractional seconds... yes +checking filesystem timestamp resolution... 0.01 +checking whether build environment is sane... yes +checking for a race-free mkdir -p... /usr/bin/mkdir -p +checking for gawk... no +checking for mawk... mawk +checking whether make sets $(MAKE)... yes +checking whether make supports nested variables... yes +checking xargs -n works... yes +checking for gcc... gcc +checking whether the C compiler works... yes +checking for C compiler default output file name... a.out +checking for suffix of executables... +checking whether we are cross compiling... no +checking for suffix of object files... o +checking whether the compiler supports GNU C... yes +checking whether gcc accepts -g... yes +checking for gcc option to enable C11 features... none needed +checking whether gcc understands -c and -o together... yes +checking whether make supports the include directive... yes (GNU style) +checking dependency style of gcc... gcc3 +checking dependency style of gcc... gcc3 +checking for ar... ar +checking the archiver (ar) interface... ar +checking how to print strings... printf +checking for a sed that does not truncate output... /usr/bin/sed +checking for grep that handles long lines and -e... /usr/bin/grep +checking for egrep... /usr/bin/grep -E +checking for fgrep... /usr/bin/grep -F +checking for ld used by gcc... /usr/bin/ld +checking if the linker (/usr/bin/ld) is GNU ld... yes +checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B +checking the name lister (/usr/bin/nm -B) interface... BSD nm +checking whether ln -s works... yes +checking the maximum length of command line arguments... 1572864 +checking how to convert x86_64-pc-linux-gnu file names to x86_64-pc-linux-gnu format... func_convert_file_noop +checking how to convert x86_64-pc-linux-gnu file names to toolchain format... func_convert_file_noop +checking for /usr/bin/ld option to reload object files... -r +checking for file... file +checking for objdump... objdump +checking how to recognize dependent libraries... pass_all +checking for dlltool... no +checking how to associate runtime and link libraries... printf %s\n +checking for ranlib... ranlib +checking for archiver @FILE support... @ +checking for strip... strip +checking command to parse /usr/bin/nm -B output from gcc object... ok +checking for sysroot... no +checking for a working dd... /usr/bin/dd +checking how to truncate binary pipes... /usr/bin/dd bs=4096 count=1 +checking for mt... mt +checking if mt is a manifest tool... no +checking for stdio.h... yes +checking for stdlib.h... yes +checking for string.h... yes +checking for inttypes.h... yes +checking for stdint.h... yes +checking for strings.h... yes +checking for sys/stat.h... yes +checking for sys/types.h... yes +checking for unistd.h... yes +checking for dlfcn.h... yes +checking for objdir... .libs +checking if gcc supports -fno-rtti -fno-exceptions... no +checking for gcc option to produce PIC... -fPIC -DPIC +checking if gcc PIC flag -fPIC -DPIC works... yes +checking if gcc static flag -static works... yes +checking if gcc supports -c -o file.o... yes +checking if gcc supports -c -o file.o... (cached) yes +checking whether the gcc linker (/usr/bin/ld -m elf_x86_64) supports shared libraries... yes +checking dynamic linker characteristics... GNU/Linux ld.so +checking how to hardcode library paths into programs... immediate +checking whether stripping libraries is possible... yes +checking if libtool supports shared libraries... yes +checking whether to build shared libraries... no +checking whether to build static libraries... yes +checking if gcc supports -Werror... yes +checking if gcc supports -std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef... yes +checking if gcc supports -Wno-overlength-strings... yes +checking if gcc supports -Wall... yes +checking if gcc supports -Wno-unused-function... yes +checking if gcc supports -Wextra... yes +checking if gcc supports -Wcast-align... yes +checking if gcc supports -Wcast-align=strict... yes +checking if gcc supports -Wconditional-uninitialized... no +checking if gcc supports -Wreserved-identifier... no +checking if gcc supports -Wtrailing-whitespace=any... no +checking if gcc supports -Wleading-whitespace=spaces... no +checking for valgrind support... +checking for x86_64 assembly availability... yes +checking that generated files are newer than configure... done +configure: creating ./config.status +config.status: creating Makefile +config.status: creating libsecp256k1.pc +config.status: executing depfiles commands +config.status: executing libtool commands + +Build Options: + with external callbacks = no + with benchmarks = no + with tests = no + with exhaustive tests = yes + with ctime tests = no + with coverage = no + with examples = no + module ecdh = yes + module recovery = no + module extrakeys = yes + module schnorrsig = yes + module musig = yes + module ellswift = yes + module silentpayments = yes + + asm = x86_64 + ecmult window size = 15 + ecmult gen table size = 86 KiB + + valgrind = no + CC = gcc + CPPFLAGS = + SECP_CFLAGS = -O2 -std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef -Wno-overlength-strings -Wall -Wno-unused-function -Wextra -Wcast-align -Wcast-align=strict + CFLAGS = -g -O2 + LDFLAGS = +make[1]: Entrando no diretório '/root/rel16/secp256k1-build' + +make all-am +make[2]: Entrando no diretório '/root/rel16/secp256k1-build' + + CC src/exhaustive_tests-tests_exhaustive.o + CCLD exhaustive_tests + CC src/libsecp256k1_la-secp256k1.lo + CC src/libsecp256k1_precomputed_la-precomputed_ecmult.lo + CC src/libsecp256k1_precomputed_la-precomputed_ecmult_gen.lo + CCLD libsecp256k1_precomputed.la + CCLD libsecp256k1.la +make[2]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[1]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[1]: Entrando no diretório '/root/rel16/secp256k1-build' + +make install-am +make[2]: Entrando no diretório '/root/rel16/secp256k1-build' + +make[3]: Entrando no diretório '/root/rel16/secp256k1-build' + + /usr/bin/mkdir -p '/usr/local/lib' + /bin/bash ./libtool --mode=install /usr/bin/install -c libsecp256k1.la '/usr/local/lib' +libtool: install: /usr/bin/install -c .libs/libsecp256k1.lai /usr/local/lib/libsecp256k1.la +libtool: install: /usr/bin/install -c .libs/libsecp256k1.a /usr/local/lib/libsecp256k1.a +libtool: install: chmod 644 /usr/local/lib/libsecp256k1.a +libtool: install: ranlib /usr/local/lib/libsecp256k1.a +libtool: finish: PATH="/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin" ldconfig -n /usr/local/lib +---------------------------------------------------------------------- +Libraries have been installed in: + /usr/local/lib + +If you ever happen to want to link against installed libraries +in a given directory, LIBDIR, you must either use libtool, and +specify the full pathname of the library, or use the '-LLIBDIR' +flag during linking and do at least one of the following: + - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable + during execution + - add LIBDIR to the 'LD_RUN_PATH' environment variable + during linking + - use the '-Wl,-rpath -Wl,LIBDIR' linker flag + - have your system administrator add LIBDIR to '/etc/ld.so.conf' + +See any operating system documentation about shared libraries for +more information, such as the ld(1) and ld.so(8) manual pages. +---------------------------------------------------------------------- + /usr/bin/mkdir -p '/usr/local/include' + /usr/bin/install -c -m 644 include/secp256k1.h include/secp256k1_preallocated.h include/secp256k1_ecdh.h include/secp256k1_extrakeys.h include/secp256k1_schnorrsig.h include/secp256k1_musig.h include/secp256k1_ellswift.h include/secp256k1_silentpayments.h '/usr/local/include' + /usr/bin/mkdir -p '/usr/local/lib/pkgconfig' + /usr/bin/install -c -m 644 libsecp256k1.pc '/usr/local/lib/pkgconfig' +make[3]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[2]: Saindo do diretório '/root/rel16/secp256k1-build' + +make[1]: Saindo do diretório '/root/rel16/secp256k1-build' + +==> libsecp256k1 done +==> building RandomX +==> RandomX pinned at 1e9d4b2df63fa6edf46b06789486e23c0fcaa55a +-- The C compiler identification is GNU 14.2.0 +-- The CXX compiler identification is GNU 14.2.0 +-- Detecting C compiler ABI info +-- Detecting C compiler ABI info - done +-- Check for working C compiler: /usr/bin/cc - skipped +-- Detecting C compile features +-- Detecting C compile features - done +-- Detecting CXX compiler ABI info +-- Detecting CXX compiler ABI info - done +-- Check for working CXX compiler: /usr/bin/c++ - skipped +-- Detecting CXX compile features +-- Detecting CXX compile features - done +-- Performing Test _maes_cxx +-- Performing Test _maes_cxx - Success +-- Setting CXX flag -maes +-- Performing Test _maes_c +-- Performing Test _maes_c - Success +-- Setting C flag -maes +-- Performing Test HAVE_SSSE3 +-- Performing Test HAVE_SSSE3 - Success +-- Performing Test HAVE_AVX2 +-- Performing Test HAVE_AVX2 - Success +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD +-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success +-- Found Threads: TRUE +-- Performing Test HAVE_CXX_ATOMICS +-- Performing Test HAVE_CXX_ATOMICS - Success +-- Performing Test HAVE_POSIX_MEMALIGN +-- Performing Test HAVE_POSIX_MEMALIGN - Success +-- Configuring done (1.0s) +-- Generating done (0.0s) +-- Build files have been written to: /root/RandomX/build +make[1]: Entrando no diretório '/root/RandomX/build' + +[ 3%] Building CXX object CMakeFiles/randomx.dir/src/aes_hash.cpp.o +[ 7%] Building C object CMakeFiles/randomx.dir/src/argon2_ref.c.o +[ 11%] Building C object CMakeFiles/randomx.dir/src/argon2_ssse3.c.o +[ 14%] Building C object CMakeFiles/randomx.dir/src/argon2_avx2.c.o +[ 18%] Building CXX object CMakeFiles/randomx.dir/src/bytecode_machine.cpp.o +[ 22%] Building CXX object CMakeFiles/randomx.dir/src/cpu.cpp.o +[ 25%] Building CXX object CMakeFiles/randomx.dir/src/dataset.cpp.o +[ 29%] Building CXX object CMakeFiles/randomx.dir/src/soft_aes.cpp.o +[ 33%] Building C object CMakeFiles/randomx.dir/src/virtual_memory.c.o +[ 37%] Building CXX object CMakeFiles/randomx.dir/src/vm_interpreted.cpp.o +[ 40%] Building CXX object CMakeFiles/randomx.dir/src/allocator.cpp.o +[ 44%] Building CXX object CMakeFiles/randomx.dir/src/assembly_generator_x86.cpp.o +[ 48%] Building CXX object CMakeFiles/randomx.dir/src/instruction.cpp.o +[ 51%] Building CXX object CMakeFiles/randomx.dir/src/randomx.cpp.o +[ 55%] Building CXX object CMakeFiles/randomx.dir/src/superscalar.cpp.o +[ 59%] Building CXX object CMakeFiles/randomx.dir/src/vm_compiled.cpp.o +[ 62%] Building CXX object CMakeFiles/randomx.dir/src/vm_interpreted_light.cpp.o +[ 66%] Building C object CMakeFiles/randomx.dir/src/argon2_core.c.o +[ 70%] Building CXX object CMakeFiles/randomx.dir/src/blake2_generator.cpp.o +[ 74%] Building CXX object CMakeFiles/randomx.dir/src/instructions_portable.cpp.o +[ 77%] Building C object CMakeFiles/randomx.dir/src/reciprocal.c.o +[ 81%] Building CXX object CMakeFiles/randomx.dir/src/virtual_machine.cpp.o +[ 85%] Building CXX object CMakeFiles/randomx.dir/src/vm_compiled_light.cpp.o +[ 88%] Building C object CMakeFiles/randomx.dir/src/blake2/blake2b.c.o +[ 92%] Building CXX object CMakeFiles/randomx.dir/src/jit_compiler_x86.cpp.o +[ 96%] Building C object CMakeFiles/randomx.dir/src/jit_compiler_x86_static.S.o +[100%] Linking CXX static library librandomx.a +[100%] Built target randomx +make[1]: Saindo do diretório '/root/RandomX/build' + +==> RandomX done +make -C src -f Makefile -j1 +make[1]: Entrando no diretório '/root/rel16/src' + +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/imgui.o imgui/imgui.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/imgui_draw.o imgui/imgui_draw.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/imgui_tables.o imgui/imgui_tables.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/imgui_widgets.o imgui/imgui_widgets.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/imgui_impl_glfw.o imgui/imgui_impl_glfw.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/imgui_impl_opengl3.o imgui/imgui_impl_opengl3.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/util.o util.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/script.o script.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/db.o db.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/net.o net.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/main.o main.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/market.o market.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -O3 -o obj/sha.o sha.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/nostr.o nostr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/randomx_pow.o randomx_pow.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btfaddr.o btfaddr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btfchan.o btfchan.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btfrv.o btfrv.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/btftunnel.o btftunnel.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/rpc.o rpc.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/selftest.o selftest.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/bip32.o bip32.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/walletcmd.o walletcmd.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/gui.o gui.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o obj/main_gui.o main_gui.cpp +g++ -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o bitflash obj/imgui.o obj/imgui_draw.o obj/imgui_tables.o obj/imgui_widgets.o obj/imgui_impl_glfw.o obj/imgui_impl_opengl3.o obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o obj/market.o obj/sha.o obj/nostr.o obj/randomx_pow.o obj/btfaddr.o obj/btfchan.o obj/btfrv.o obj/btftunnel.o obj/rpc.o obj/selftest.o obj/bip32.o obj/walletcmd.o obj/gui.o obj/main_gui.o -L/usr/local/lib -lsecp256k1 -L/root/RandomX/build -lrandomx -lsodium -lssl -lcrypto -ldb_cxx -lpthread -lglfw -lGL +Built: bitflash +make[1]: Saindo do diretório '/root/rel16/src' + +strip src/bitflash +make -f Makefile appimage +make[1]: Entrando no diretório '/root/rel16' + +==> building AppImage + bundled libsodium.so.23 + bundled libdb_cxx-5.3.so + bundled libglfw.so.3 +Built: Bitflash-1.2.16-x86_64.AppImage +make[1]: Saindo do diretório '/root/rel16' + +make -f Makefile linux-node +make[1]: Entrando no diretório '/root/rel16' + +Lendo listas de pacotes... +Construindo árvore de dependências... +Lendo informação de estado... +build-essential já é a versão mais nova (12.12). +cmake já é a versão mais nova (3.31.6-2). +git já é a versão mais nova (1:2.47.3-0+deb13u1). +pkg-config já é a versão mais nova (1.8.1-4). +autoconf já é a versão mais nova (2.72-3.1). +libtool já é a versão mais nova (2.5.4-4). +libssl-dev já é a versão mais nova (3.5.6-1~deb13u2). +libdb5.3++-dev já é a versão mais nova (5.3.28+dfsg2-9). +libsodium-dev já é a versão mais nova (1.0.18-1+deb13u1). +nlohmann-json3-dev já é a versão mais nova (3.11.3-2.1). +libboost-system-dev já é a versão mais nova (1.83.0.2+b2). +libglfw3-dev já é a versão mais nova (3.4-3). +libgl-dev já é a versão mais nova (1.7.0-1+b2). +python3-pil já é a versão mais nova (11.1.0-5+deb13u4). +clang já é a versão mais nova (1:19.0-63). +0 pacotes atualizados, 0 pacotes novos instalados, 0 a serem removidos e 49 não atualizados. +==> libsecp256k1 already installed +==> RandomX already built +make -C src -f Makefile bitflash-node -j1 +make[2]: Entrando no diretório '/root/rel16/src' + +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/util.o util.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/script.o script.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/db.o db.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/net.o net.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/main.o main.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/market.o market.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -O3 -o obj-node/sha.o sha.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/nostr.o nostr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/randomx_pow.o randomx_pow.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btfaddr.o btfaddr.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btfchan.o btfchan.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btfrv.o btfrv.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/btftunnel.o btftunnel.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/rpc.o rpc.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/selftest.o selftest.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/bip32.o bip32.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/walletcmd.o walletcmd.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/main_gui.o main_gui.cpp +g++ -c -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -DBITFLASH_NO_GUI -o obj-node/headless.o headless.cpp +g++ -std=gnu++14 -O2 -Wformat -Werror=format -Wno-deprecated-declarations -Wno-write-strings -Wno-narrowing -Wno-unused-result -fpermissive -pthread -DSECP256K1_STATIC -I/usr/local/include -I/root/RandomX/src -I/usr/include/nlohmann -Iimgui -o bitflash-node obj-node/util.o obj-node/script.o obj-node/db.o obj-node/net.o obj-node/main.o obj-node/market.o obj-node/sha.o obj-node/nostr.o obj-node/randomx_pow.o obj-node/btfaddr.o obj-node/btfchan.o obj-node/btfrv.o obj-node/btftunnel.o obj-node/rpc.o obj-node/selftest.o obj-node/bip32.o obj-node/walletcmd.o obj-node/main_gui.o obj-node/headless.o -L/usr/local/lib -lsecp256k1 -L/root/RandomX/build -lrandomx -lsodium -lssl -lcrypto -ldb_cxx -lpthread +Built: bitflash-node (headless, no libGL needed) +make[2]: Saindo do diretório '/root/rel16/src' + +strip src/bitflash-node +cp src/bitflash-node bitflash-node-1.2.16-x86_64 +Built: bitflash-node-1.2.16-x86_64 +make[1]: Saindo do diretório '/root/rel16' + diff --git a/docs/site.md b/docs/site.md index 522da10..9526a61 100644 --- a/docs/site.md +++ b/docs/site.md @@ -42,8 +42,8 @@ The docs index should expose these source files: Each release remains under its versioned directory: ```text -https://releases.bitflash.network/v1.2.18/SHA256SUMS -https://releases.bitflash.network/v1.2.18/SHA256SUMS.asc +https://releases.bitflash.network/v1.2.19/SHA256SUMS +https://releases.bitflash.network/v1.2.19/SHA256SUMS.asc ``` The release root should also alias the latest files: diff --git a/scripts/__pycache__/bitflash_chain.cpython-313.pyc b/scripts/__pycache__/bitflash_chain.cpython-313.pyc new file mode 100644 index 0000000..47a7995 Binary files /dev/null and b/scripts/__pycache__/bitflash_chain.cpython-313.pyc differ -- cgit v1.2.3 From c49b92a9a79a398b51200e69f7dde8a467b9c925 Mon Sep 17 00:00:00 2001 From: Nsable-sh Date: Fri, 14 Aug 2026 15:03:21 -0300 Subject: wallet: add experimental SQLite record store --- .github/workflows/ci.yml | 1 + Makefile | 8 +- docs/storage.md | 19 ++++ src/Makefile | 10 +- src/main_gui.cpp | 3 +- src/makefile.mingw | 8 +- src/selftest.cpp | 108 +++++++++++++++++++- src/wallet_sqlite.cpp | 254 +++++++++++++++++++++++++++++++++++++++++++++++ src/wallet_sqlite.h | 40 ++++++++ 9 files changed, 439 insertions(+), 12 deletions(-) create mode 100644 src/wallet_sqlite.cpp create mode 100644 src/wallet_sqlite.h (limited to 'Makefile') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4045f4..e22b5a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,7 @@ jobs: mingw-w64-ucrt-x86_64-glfw mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-db + mingw-w64-ucrt-x86_64-sqlite3 mingw-w64-ucrt-x86_64-libsodium mingw-w64-ucrt-x86_64-nlohmann-json mingw-w64-ucrt-x86_64-boost diff --git a/Makefile b/Makefile index 60d1227..fab2507 100644 --- a/Makefile +++ b/Makefile @@ -43,10 +43,11 @@ deps-apt: @if command -v apt-get >/dev/null 2>&1; then \ $(SUDO) apt-get install -y build-essential cmake git pkg-config autoconf \ libtool libssl-dev libdb5.3++-dev libsodium-dev nlohmann-json3-dev \ - libboost-system-dev libglfw3-dev libgl-dev python3-pil clang; \ + libboost-system-dev libglfw3-dev libgl-dev libsqlite3-dev \ + python3-pil clang; \ else \ echo "Not an apt system — install: g++ cmake git autoconf libtool"; \ - echo " libssl libdb++ libsodium nlohmann-json boost glfw3 opengl python3-pil"; \ + echo " libssl libdb++ libsodium nlohmann-json boost glfw3 opengl sqlite3 python3-pil"; \ fi deps-secp256k1: @@ -113,7 +114,7 @@ img = ico.convert('RGBA'); \ img.save('/tmp/bitflash.AppDir/bitflash.png'); \ import shutil; shutil.copy('/tmp/bitflash.AppDir/bitflash.png', \ '/tmp/bitflash.AppDir/usr/share/icons/hicolor/256x256/apps/bitflash.png')" - @for lib in libsodium.so.23 libdb_cxx-5.3.so libglfw.so.3; do \ + @for lib in libsodium.so.23 libdb_cxx-5.3.so libsqlite3.so.0 libglfw.so.3; do \ path=$$(ldconfig -p | grep " $$lib " | awk '{print $$NF}' | head -1); \ [ -z "$$path" ] && path=$$(find /usr/lib /lib -name "$$lib" 2>/dev/null | head -1); \ [ -n "$$path" ] && cp -L "$$path" /tmp/bitflash.AppDir/usr/lib/ && echo " bundled $$lib" || echo " missing $$lib"; \ @@ -131,6 +132,7 @@ deps-windows: mingw-w64-ucrt-x86_64-glfw \ mingw-w64-ucrt-x86_64-openssl \ mingw-w64-ucrt-x86_64-db \ + mingw-w64-ucrt-x86_64-sqlite3 \ mingw-w64-ucrt-x86_64-libsodium \ mingw-w64-ucrt-x86_64-nlohmann-json \ mingw-w64-ucrt-x86_64-boost \ diff --git a/docs/storage.md b/docs/storage.md index c1cda45..f75f9b9 100644 --- a/docs/storage.md +++ b/docs/storage.md @@ -85,6 +85,25 @@ A future wallet backend must keep these properties: - recovery phrase encrypted and locked, requiring unlock before coverage can be audited. +## Experimental SQLite Wallet Store + +The SQLite wallet path starts as a byte-preserving record store, not as a new +wallet format: + +```sql +CREATE TABLE wallet_records ( + key BLOB PRIMARY KEY NOT NULL, + value BLOB NOT NULL +); +PRAGMA user_version=1; +``` + +Keys and values are the same serialized `CDataStream` bytes used by `wallet.dat`. +The first implementation is exercised only by `-selftest=wallet-sqlite`; the +runtime wallet still opens Berkeley DB. The purpose is to prove schema creation, +raw record write/read, close/reopen behavior, and value preservation before any +BDB-to-SQLite migration or runtime backend flag exists. + ## `blkindex.dat` `blkindex.dat` is accessed through `CTxDB`. diff --git a/src/Makefile b/src/Makefile index 19ad33a..cfa40f6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -40,7 +40,7 @@ FUZZ_LDFLAGS = -fsanitize=fuzzer,address,undefined LIBS = -L$(SECP_LIB) -lsecp256k1 \ -L$(RANDOMX_DIR)/build -lrandomx \ - -lsodium -lssl -lcrypto -ldb_cxx -lpthread \ + -lsodium -lssl -lcrypto -ldb_cxx -lsqlite3 -lpthread \ -lglfw -lGL # Every header a .cpp here includes has to be listed, not just the interesting @@ -53,7 +53,7 @@ LIBS = -L$(SECP_LIB) -lsecp256k1 \ HEADERS = headers_core.h headers.h util.h main.h serialize.h uint256.h \ key.h bignum.h script.h db.h base58.h net.h nostr.h \ randomx_pow.h btfaddr.h btfchan.h btfrv.h btftunnel.h market.h \ - selftest.h walletcmd.h compat.h sockcount.h proxy.h tor.h font_roboto.h + selftest.h walletcmd.h wallet_sqlite.h compat.h sockcount.h proxy.h tor.h font_roboto.h IMGUI_OBJS = obj/imgui.o obj/imgui_draw.o obj/imgui_tables.o \ obj/imgui_widgets.o obj/imgui_impl_glfw.o obj/imgui_impl_opengl3.o @@ -61,7 +61,8 @@ IMGUI_OBJS = obj/imgui.o obj/imgui_draw.o obj/imgui_tables.o \ NODE_OBJS = obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \ obj/market.o obj/sha.o obj/nostr.o obj/randomx_pow.o \ obj/btfaddr.o obj/btfchan.o obj/btfrv.o obj/btftunnel.o obj/rpc.o \ - obj/selftest.o obj/bip32.o obj/walletcmd.o obj/proxy.o obj/tor.o + obj/selftest.o obj/bip32.o obj/walletcmd.o obj/wallet_sqlite.o \ + obj/proxy.o obj/tor.o GUI_OBJS = obj/gui.o obj/main_gui.o @@ -116,7 +117,7 @@ bitflash: $(IMGUI_OBJS) $(NODE_OBJS) $(GUI_OBJS) NODE_LIBS = -L$(SECP_LIB) -lsecp256k1 \ -L$(RANDOMX_DIR)/build -lrandomx \ - -lsodium -lssl -lcrypto -ldb_cxx -lpthread + -lsodium -lssl -lcrypto -ldb_cxx -lsqlite3 -lpthread NODE_ONLY_OBJS = $(patsubst obj/%,obj-node/%,$(NODE_OBJS)) \ obj-node/main_gui.o obj-node/headless.o @@ -187,6 +188,7 @@ tests: test_bip32 bitflash-node ./bitflash-node -selftest=wallet-keypool ./bitflash-node -selftest=wallet-hd ./bitflash-node -selftest=wallet-format + ./bitflash-node -selftest=wallet-sqlite ./bitflash-node -selftest=wallet-crypto ./bitflash-node -selftest=wallet-encrypt ./bitflash-node -selftest=net-message diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 705b4ef..965c818 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -114,7 +114,8 @@ static void PrintUsage() printf(" /gen\n"); printf(" /nogui or /daemon\n"); printf(" /selftest=wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity,\n"); - printf(" db-env-reopen, wallet-crypto, wallet-encrypt, wallet-portability,\n"); + printf(" db-env-reopen, wallet-sqlite, wallet-crypto, wallet-encrypt,\n"); + printf(" wallet-portability,\n"); printf(" net-message,\n"); printf(" consensus-limits, pool-stratum,\n"); printf(" parse-money, socks5-proxy, or managed-tor\n"); diff --git a/src/makefile.mingw b/src/makefile.mingw index 333be96..2ff4e11 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -24,7 +24,7 @@ CXXFLAGS = -std=gnu++14 -O2 $(WARNFLAGS) -fpermissive -pthread \ LIBS = -L$(DEPS)/lib -lsecp256k1 \ -L$(RANDOMX)/build -lrandomx \ - -lsodium -lssl -lcrypto -ldb_cxx -lpthread \ + -lsodium -lssl -lcrypto -ldb_cxx -lsqlite3 -lpthread \ -LC:/msys64/ucrt64/lib \ -lglfw3 -lopengl32 -lgdi32 \ -lkernel32 -luser32 -lcomdlg32 -lwinspool -lwinmm \ @@ -37,7 +37,8 @@ IMGUI_OBJS = obj/imgui.o obj/imgui_draw.o obj/imgui_tables.o \ NODE_OBJS = obj/util.o obj/script.o obj/db.o obj/net.o obj/main.o \ obj/market.o obj/sha.o obj/nostr.o obj/randomx_pow.o \ obj/btfaddr.o obj/btfchan.o obj/btfrv.o obj/btftunnel.o obj/rpc.o \ - obj/selftest.o obj/bip32.o obj/walletcmd.o obj/proxy.o obj/tor.o + obj/selftest.o obj/bip32.o obj/walletcmd.o obj/wallet_sqlite.o \ + obj/proxy.o obj/tor.o GUI_OBJS = obj/gui.o obj/main_gui.o obj/bitflash_res.o @@ -51,7 +52,7 @@ GUI_OBJS = obj/gui.o obj/main_gui.o obj/bitflash_res.o HEADERS = headers_core.h headers.h util.h main.h serialize.h uint256.h \ key.h bignum.h script.h db.h base58.h net.h nostr.h \ randomx_pow.h btfaddr.h btfchan.h btfrv.h btftunnel.h market.h \ - selftest.h walletcmd.h sockcount.h proxy.h tor.h compat.h font_roboto.h + selftest.h walletcmd.h wallet_sqlite.h sockcount.h proxy.h tor.h compat.h font_roboto.h all: bitflash.exe @@ -107,6 +108,7 @@ tests: test_bip32.exe bitflash.exe ./bitflash.exe -selftest=wallet-keypool ./bitflash.exe -selftest=wallet-hd ./bitflash.exe -selftest=wallet-format + ./bitflash.exe -selftest=wallet-sqlite ./bitflash.exe -selftest=wallet-crypto ./bitflash.exe -selftest=wallet-encrypt ./bitflash.exe -selftest=net-message diff --git a/src/selftest.cpp b/src/selftest.cpp index 31c168f..f9c4a8e 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp @@ -13,6 +13,7 @@ #include "sockcount.h" #include "tor.h" #include "walletcmd.h" +#include "wallet_sqlite.h" extern int RunPoolStratumSelfTest(); @@ -62,6 +63,11 @@ static std::string HexStrLocal(const std::vector& v) return out; } +static vector DataStreamBytes(const CDataStream& ss) +{ + return vector(ss.begin(), ss.end()); +} + static bool MakeTempDir(std::string& out) { #ifdef _WIN32 @@ -1030,6 +1036,104 @@ static int RunDbEnvReopenSelfTest() return nFail == 0 ? 0 : 1; } +static int RunWalletSQLiteSelfTest() +{ + fflush(stdout); + printf("wallet-sqlite self-test\n"); + + std::string tmp; + if (!MakeTempDir(tmp)) + { + printf(" FAIL could not create a temporary data directory\n"); + return 1; + } + + int nFail = 0; + string strPath = tmp + "/wallet.sqlite"; + string strError; + + try + { + CDataStream ssKeySetting(SER_DISK); + ssKeySetting << make_pair(string("setting"), string("sqlite-roundtrip")); + CDataStream ssValueSetting(SER_DISK); + ssValueSetting << (int64)424242; + + vector vchPubKey; + vchPubKey.push_back(0x04); + for (int i = 0; i < 64; i++) + vchPubKey.push_back((unsigned char)i); + CDataStream ssKeyDefault(SER_DISK); + ssKeyDefault << string("defaultkey"); + CDataStream ssValueDefault(SER_DISK); + ssValueDefault << vchPubKey; + + { + CWalletDBSQLite db; + nFail += Check(db.Open(strPath, strError), + "SQLite wallet opens and creates schema") ? 0 : 1; + nFail += Check(db.BeginTransaction(strError), + "SQLite wallet begins a write transaction") ? 0 : 1; + nFail += Check(db.WriteRecord(DataStreamBytes(ssKeySetting), + DataStreamBytes(ssValueSetting), + strError), + "SQLite wallet writes a serialized setting record") ? 0 : 1; + nFail += Check(db.WriteRecord(DataStreamBytes(ssKeyDefault), + DataStreamBytes(ssValueDefault), + strError), + "SQLite wallet writes a serialized defaultkey record") ? 0 : 1; + nFail += Check(db.CommitTransaction(strError), + "SQLite wallet commits a write transaction") ? 0 : 1; + int nCount = 0; + nFail += Check(db.CountRecords(nCount, strError) && nCount == 2, + "SQLite wallet counts raw records") ? 0 : 1; + } + + { + CWalletDBSQLite db; + nFail += Check(db.Open(strPath, strError), + "SQLite wallet reopens") ? 0 : 1; + vector vchRead; + nFail += Check(db.ReadRecord(DataStreamBytes(ssKeySetting), + vchRead, + strError), + "SQLite wallet reads a serialized setting record") ? 0 : 1; + int64 nReadValue = 0; + CDataStream ssRead(vchRead, SER_DISK); + ssRead >> nReadValue; + nFail += Check(!ssRead.fail() && nReadValue == 424242, + "SQLite wallet preserves serialized values byte-for-byte") ? 0 : 1; + + vchRead.clear(); + nFail += Check(db.ReadRecord(DataStreamBytes(ssKeyDefault), + vchRead, + strError), + "SQLite wallet reads a serialized defaultkey record") ? 0 : 1; + vector vchReadPubKey; + CDataStream ssReadDefault(vchRead, SER_DISK); + ssReadDefault >> vchReadPubKey; + nFail += Check(!ssReadDefault.fail() && vchReadPubKey == vchPubKey, + "SQLite wallet preserves public key blobs") ? 0 : 1; + } + } + catch (const std::exception& e) + { + printf(" FAIL exception: %s\n", e.what()); + nFail++; + } + catch (...) + { + printf(" FAIL unknown exception\n"); + nFail++; + } + + RemoveTree(tmp); + printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED", + nFail, nFail == 1 ? "" : "s"); + fflush(stdout); + return nFail == 0 ? 0 : 1; +} + static void ClearWalletRuntimeForTest() { CRITICAL_BLOCK(cs_mapKeys) @@ -2289,6 +2393,8 @@ int RunSelfTest(const std::string& name) return RunWalletStorageSanitySelfTest(); if (name == "db-env-reopen") return RunDbEnvReopenSelfTest(); + if (name == "wallet-sqlite") + return RunWalletSQLiteSelfTest(); if (name == "wallet-crypto") return RunWalletCryptoSelfTest(); if (name == "wallet-encrypt") @@ -2309,6 +2415,6 @@ int RunSelfTest(const std::string& name) return RunManagedTorSelfTest(); printf("Unknown self-test '%s'\n", name.c_str()); - printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-crypto, wallet-encrypt, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n"); + printf("Known self-tests: wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity, db-env-reopen, wallet-sqlite, wallet-crypto, wallet-encrypt, wallet-portability, net-message, consensus-limits, pool-stratum, parse-money, socks5-proxy, managed-tor\n"); return 1; } diff --git a/src/wallet_sqlite.cpp b/src/wallet_sqlite.cpp new file mode 100644 index 0000000..4104ac6 --- /dev/null +++ b/src/wallet_sqlite.cpp @@ -0,0 +1,254 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. + +#include "headers.h" +#include "wallet_sqlite.h" + +static void SetSQLiteError(sqlite3* pdb, const string& strContext, + string& strError) +{ + if (pdb) + strError = strContext + ": " + sqlite3_errmsg(pdb); + else + strError = strContext; +} + +CWalletDBSQLite::CWalletDBSQLite() : pdb(NULL) +{ +} + +CWalletDBSQLite::~CWalletDBSQLite() +{ + Close(); +} + +bool CWalletDBSQLite::Open(const string& strPath, string& strError) +{ + Close(); + + int ret = sqlite3_open_v2(strPath.c_str(), &pdb, + SQLITE_OPEN_READWRITE | + SQLITE_OPEN_CREATE | + SQLITE_OPEN_FULLMUTEX, + NULL); + if (ret != SQLITE_OK) + { + SetSQLiteError(pdb, "cannot open SQLite wallet", strError); + Close(); + return false; + } + + sqlite3_busy_timeout(pdb, 5000); + + if (!Exec("PRAGMA journal_mode=WAL;", strError)) + { + Close(); + return false; + } + if (!Exec("PRAGMA synchronous=FULL;", strError)) + { + Close(); + return false; + } + if (!InitSchema(strError)) + { + Close(); + return false; + } + return true; +} + +void CWalletDBSQLite::Close() +{ + if (pdb) + { + sqlite3_close(pdb); + pdb = NULL; + } +} + +bool CWalletDBSQLite::BeginTransaction(string& strError) +{ + if (!pdb) + { + strError = "SQLite wallet is not open"; + return false; + } + return Exec("BEGIN IMMEDIATE;", strError); +} + +bool CWalletDBSQLite::CommitTransaction(string& strError) +{ + if (!pdb) + { + strError = "SQLite wallet is not open"; + return false; + } + return Exec("COMMIT;", strError); +} + +bool CWalletDBSQLite::RollbackTransaction(string& strError) +{ + if (!pdb) + { + strError = "SQLite wallet is not open"; + return false; + } + return Exec("ROLLBACK;", strError); +} + +bool CWalletDBSQLite::Exec(const char* pszSql, string& strError) +{ + char* pszErr = NULL; + int ret = sqlite3_exec(pdb, pszSql, NULL, NULL, &pszErr); + if (ret != SQLITE_OK) + { + if (pszErr) + { + strError = pszErr; + sqlite3_free(pszErr); + } + else + SetSQLiteError(pdb, "SQLite exec failed", strError); + return false; + } + return true; +} + +bool CWalletDBSQLite::InitSchema(string& strError) +{ + return Exec("CREATE TABLE IF NOT EXISTS wallet_records (" + "key BLOB PRIMARY KEY NOT NULL," + "value BLOB NOT NULL" + ");", + strError) && + Exec("PRAGMA user_version=1;", strError); +} + +bool CWalletDBSQLite::WriteRecord(const vector& vchKey, + const vector& vchValue, + string& strError) +{ + if (!pdb) + { + strError = "SQLite wallet is not open"; + return false; + } + if (vchKey.empty()) + { + strError = "SQLite wallet record key is empty"; + return false; + } + + sqlite3_stmt* stmt = NULL; + const char* pszSql = + "INSERT OR REPLACE INTO wallet_records(key, value) VALUES(?, ?);"; + int ret = sqlite3_prepare_v2(pdb, pszSql, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + SetSQLiteError(pdb, "cannot prepare SQLite wallet write", strError); + return false; + } + + ret = sqlite3_bind_blob(stmt, 1, &vchKey[0], (int)vchKey.size(), + SQLITE_TRANSIENT); + if (ret == SQLITE_OK) + ret = sqlite3_bind_blob(stmt, 2, + vchValue.empty() ? NULL : &vchValue[0], + (int)vchValue.size(), + SQLITE_TRANSIENT); + if (ret == SQLITE_OK) + ret = sqlite3_step(stmt); + + bool fOk = (ret == SQLITE_DONE); + if (!fOk) + SetSQLiteError(pdb, "cannot write SQLite wallet record", strError); + sqlite3_finalize(stmt); + return fOk; +} + +bool CWalletDBSQLite::ReadRecord(const vector& vchKey, + vector& vchValueRet, + string& strError) +{ + vchValueRet.clear(); + if (!pdb) + { + strError = "SQLite wallet is not open"; + return false; + } + if (vchKey.empty()) + { + strError = "SQLite wallet record key is empty"; + return false; + } + + sqlite3_stmt* stmt = NULL; + const char* pszSql = "SELECT value FROM wallet_records WHERE key = ?;"; + int ret = sqlite3_prepare_v2(pdb, pszSql, -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + SetSQLiteError(pdb, "cannot prepare SQLite wallet read", strError); + return false; + } + + ret = sqlite3_bind_blob(stmt, 1, &vchKey[0], (int)vchKey.size(), + SQLITE_TRANSIENT); + if (ret != SQLITE_OK) + { + SetSQLiteError(pdb, "cannot bind SQLite wallet key", strError); + sqlite3_finalize(stmt); + return false; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ROW) + { + const unsigned char* pch = + (const unsigned char*)sqlite3_column_blob(stmt, 0); + int nBytes = sqlite3_column_bytes(stmt, 0); + if (nBytes > 0 && pch) + vchValueRet.assign(pch, pch + nBytes); + sqlite3_finalize(stmt); + return true; + } + + if (ret == SQLITE_DONE) + strError = "SQLite wallet record not found"; + else + SetSQLiteError(pdb, "cannot read SQLite wallet record", strError); + sqlite3_finalize(stmt); + return false; +} + +bool CWalletDBSQLite::CountRecords(int& nRecordsRet, string& strError) +{ + nRecordsRet = 0; + if (!pdb) + { + strError = "SQLite wallet is not open"; + return false; + } + + sqlite3_stmt* stmt = NULL; + int ret = sqlite3_prepare_v2(pdb, + "SELECT COUNT(*) FROM wallet_records;", + -1, &stmt, NULL); + if (ret != SQLITE_OK) + { + SetSQLiteError(pdb, "cannot prepare SQLite wallet count", strError); + return false; + } + + ret = sqlite3_step(stmt); + if (ret != SQLITE_ROW) + { + SetSQLiteError(pdb, "cannot count SQLite wallet records", strError); + sqlite3_finalize(stmt); + return false; + } + + nRecordsRet = sqlite3_column_int(stmt, 0); + sqlite3_finalize(stmt); + return true; +} diff --git a/src/wallet_sqlite.h b/src/wallet_sqlite.h new file mode 100644 index 0000000..9812d3a --- /dev/null +++ b/src/wallet_sqlite.h @@ -0,0 +1,40 @@ +// Copyright (c) 2026 Bitflash developers +// Distributed under the MIT/X11 software license. + +#ifndef BITFLASH_WALLET_SQLITE_H +#define BITFLASH_WALLET_SQLITE_H + +#include + +class CWalletDBSQLite +{ +public: + CWalletDBSQLite(); + ~CWalletDBSQLite(); + + bool Open(const string& strPath, string& strError); + void Close(); + + bool BeginTransaction(string& strError); + bool CommitTransaction(string& strError); + bool RollbackTransaction(string& strError); + + bool WriteRecord(const vector& vchKey, + const vector& vchValue, + string& strError); + bool ReadRecord(const vector& vchKey, + vector& vchValueRet, + string& strError); + bool CountRecords(int& nRecordsRet, string& strError); + +private: + sqlite3* pdb; + + bool Exec(const char* pszSql, string& strError); + bool InitSchema(string& strError); + + CWalletDBSQLite(const CWalletDBSQLite&); + void operator=(const CWalletDBSQLite&); +}; + +#endif -- cgit v1.2.3 From 6cf299c79ee8c9855254cb0d79fad3e476f81f43 Mon Sep 17 00:00:00 2001 From: bitflash Date: Wed, 19 Aug 2026 11:37:28 -0300 Subject: build: VERSION 1.2.20 Name the release artifacts for v1.2.20. Matches BITFLASH_VERSION_STRING. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index fab2507..8696be4 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.19 +VERSION := 1.2.20 SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1 SECP256K1_COMMIT := 7fecac74aed8e1fd9078380d67dd04663705c989 -- cgit v1.2.3 From 8f8a02e8ea3358ddec043bb9b1f615d0d1fc9fc7 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 19 Aug 2026 18:17:16 +0000 Subject: build: pin the dependencies that decide consensus, and check what we run The two dependency clones were `git clone --depth 1 ` 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) --- Makefile | 108 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 23 deletions(-) (limited to 'Makefile') 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) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") VERSION := 1.2.15 +# ---- Pinned third-party sources ------------------------------------------- +# +# These were `git clone --depth 1 ` with no revision, which resolves to +# whatever the default branch happens to point at the moment the build runs. +# For a dependency that only had to link, that is untidy. For these two it is +# not: +# +# RandomX is the proof of work. Its master is not frozen -- v2.0 (Mar 2026) +# changed the algorithm -- so two builds of the same Bitflash commit, made a +# few weeks apart, can compute different hashes for the same header. That is +# not a supply-chain worry, it is a chain split arriving as a build artifact, +# with no version recorded anywhere to explain it afterwards. +# +# libsecp256k1 is signature verification, i.e. the rule deciding who may +# spend. Whatever is on master on the day of the build is what enforces it. +# +# Pinned to full commit ids, not tags: a tag is a mutable pointer, and `git +# checkout ` is the only form here that verifies what it fetched (git +# resolves the object by its own hash). Bump deliberately, and rebuild and +# resync before shipping the result. +# +# RandomX pin is the commit this tree has been building and syncing against +# (post-v2.0.1 master, 2026-05-24) -- chosen to change nothing today. +SECP256K1_REPO := https://github.com/bitcoin-core/secp256k1 +SECP256K1_COMMIT := 6e2c8bc4ecdc6e71dbe7a368f360d8d453ce435d +RANDOMX_REPO := https://github.com/tevador/RandomX +RANDOMX_COMMIT := 1e9d4b2df63fa6edf46b06789486e23c0fcaa55a + +# appimagetool came from the "continuous" release, a tag that is moved in place +# on every upstream push, fetched over the network and executed. Pinned to a +# numbered release and checked by digest before it is allowed to run. +APPIMAGETOOL_URL := https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-x86_64.AppImage +APPIMAGETOOL_SHA256 := ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0 + # ---- Linux ---------------------------------------------------------------- linux: deps-linux @@ -47,8 +81,12 @@ deps-secp256k1: @if [ ! -f /usr/local/lib/libsecp256k1.a ]; then \ echo "==> building libsecp256k1"; \ rm -rf $(ROOT)/secp256k1-build; \ - git clone --depth 1 https://github.com/bitcoin-core/secp256k1 $(ROOT)/secp256k1-build; \ - cd $(ROOT)/secp256k1-build && ./autogen.sh && \ + git init -q $(ROOT)/secp256k1-build; \ + cd $(ROOT)/secp256k1-build && \ + git remote add origin $(SECP256K1_REPO) && \ + git fetch -q --depth 1 origin $(SECP256K1_COMMIT) && \ + git checkout -q $(SECP256K1_COMMIT) && \ + ./autogen.sh && \ ./configure --enable-module-schnorrsig --enable-module-extrakeys \ --disable-shared --with-pic --disable-benchmark --disable-tests && \ make -j$(NPROC) && $(SUDO) make install && $(SUDO) ldconfig; \ @@ -61,7 +99,11 @@ deps-randomx: @if [ ! -f $(HOME)/RandomX/build/librandomx.a ]; then \ echo "==> building RandomX"; \ rm -rf $(HOME)/RandomX; \ - git clone --depth 1 https://github.com/tevador/RandomX $(HOME)/RandomX; \ + git init -q $(HOME)/RandomX; \ + cd $(HOME)/RandomX && \ + git remote add origin $(RANDOMX_REPO) && \ + git fetch -q --depth 1 origin $(RANDOMX_COMMIT) && \ + git checkout -q $(RANDOMX_COMMIT); \ mkdir -p $(HOME)/RandomX/build; \ cd $(HOME)/RandomX/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \ make -j$(NPROC) randomx; \ @@ -70,37 +112,57 @@ deps-randomx: echo "==> RandomX already built"; \ fi +# APPDIR and the tool both used fixed paths under /tmp, on a directory every +# local account can write. `[ ! -x /tmp/appimagetool ]` means an executable +# already sitting at that name is taken as the tool and run, so anyone with a +# shell on the build machine could have put one there first and had it execute +# as whoever ran make; `rm -rf /tmp/bitflash.AppDir` then mkdir is the same +# problem one step later, through symlinks. Both now live under the build tree, +# which the build already owns. +APPDIR := $(ROOT)/build/bitflash.AppDir +APPIMAGETOOL := $(ROOT)/build/appimagetool + appimage: src/bitflash @echo "==> building AppImage" - @if [ ! -x /tmp/appimagetool ]; then \ - wget -q "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" \ - -O /tmp/appimagetool && chmod +x /tmp/appimagetool; \ + @mkdir -p $(ROOT)/build + @if [ ! -x "$(APPIMAGETOOL)" ]; then \ + echo " fetching appimagetool"; \ + wget -q "$(APPIMAGETOOL_URL)" -O "$(APPIMAGETOOL).tmp" || \ + { echo " ERROR: appimagetool download failed"; rm -f "$(APPIMAGETOOL).tmp"; exit 1; }; \ + echo "$(APPIMAGETOOL_SHA256) $(APPIMAGETOOL).tmp" | sha256sum -c - >/dev/null 2>&1 || \ + { echo " ERROR: appimagetool digest mismatch, refusing to run it"; \ + echo " expected $(APPIMAGETOOL_SHA256)"; \ + echo " got $$(sha256sum "$(APPIMAGETOOL).tmp" | cut -d" " -f1)"; \ + rm -f "$(APPIMAGETOOL).tmp"; exit 1; }; \ + chmod +x "$(APPIMAGETOOL).tmp" && mv "$(APPIMAGETOOL).tmp" "$(APPIMAGETOOL)"; \ fi - @rm -rf /tmp/bitflash.AppDir - @mkdir -p /tmp/bitflash.AppDir/usr/bin \ - /tmp/bitflash.AppDir/usr/lib \ - /tmp/bitflash.AppDir/usr/share/applications \ - /tmp/bitflash.AppDir/usr/share/icons/hicolor/256x256/apps - @cp src/bitflash /tmp/bitflash.AppDir/usr/bin/bitflash + @rm -rf $(APPDIR) + @mkdir -p $(APPDIR)/usr/bin \ + $(APPDIR)/usr/lib \ + $(APPDIR)/usr/share/applications \ + $(APPDIR)/usr/share/icons/hicolor/256x256/apps + @cp src/bitflash $(APPDIR)/usr/bin/bitflash @printf '#!/bin/sh\nHERE="$$(dirname "$$(readlink -f "$$0")")"\nexport LD_LIBRARY_PATH="$$HERE/usr/lib:$$LD_LIBRARY_PATH"\nexec "$$HERE/usr/bin/bitflash" "$$@"\n' \ - > /tmp/bitflash.AppDir/AppRun && chmod +x /tmp/bitflash.AppDir/AppRun + > $(APPDIR)/AppRun && chmod +x $(APPDIR)/AppRun @printf '[Desktop Entry]\nName=Bitflash\nExec=bitflash\nIcon=bitflash\nType=Application\nCategories=Finance;\n' \ - > /tmp/bitflash.AppDir/bitflash.desktop - @cp /tmp/bitflash.AppDir/bitflash.desktop \ - /tmp/bitflash.AppDir/usr/share/applications/ - @python3 -c "\ + > $(APPDIR)/bitflash.desktop + @cp $(APPDIR)/bitflash.desktop \ + $(APPDIR)/usr/share/applications/ + @APPDIR=$(APPDIR) python3 -c "\ +import os; \ from PIL import Image; \ +d = os.environ['APPDIR']; \ ico = Image.open('src/rc/bitcoin.ico'); \ img = ico.convert('RGBA'); \ -img.save('/tmp/bitflash.AppDir/bitflash.png'); \ -import shutil; shutil.copy('/tmp/bitflash.AppDir/bitflash.png', \ -'/tmp/bitflash.AppDir/usr/share/icons/hicolor/256x256/apps/bitflash.png')" +img.save(d + '/bitflash.png'); \ +import shutil; shutil.copy(d + '/bitflash.png', \ +d + '/usr/share/icons/hicolor/256x256/apps/bitflash.png')" @for lib in libsodium.so.23 libdb_cxx-5.3.so libglfw.so.3; do \ path=$$(ldconfig -p | grep " $$lib " | awk '{print $$NF}' | head -1); \ [ -z "$$path" ] && path=$$(find /usr/lib /lib -name "$$lib" 2>/dev/null | head -1); \ - [ -n "$$path" ] && cp -L "$$path" /tmp/bitflash.AppDir/usr/lib/ && echo " bundled $$lib" || echo " missing $$lib"; \ + [ -n "$$path" ] && cp -L "$$path" $(APPDIR)/usr/lib/ && echo " bundled $$lib" || echo " missing $$lib"; \ done - @ARCH=x86_64 /tmp/appimagetool --no-appstream /tmp/bitflash.AppDir \ + @ARCH=x86_64 $(APPIMAGETOOL) --no-appstream $(APPDIR) \ $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage 2>&1 | grep -E "^Built|^Error" || true @echo "Built: Bitflash-$(VERSION)-x86_64.AppImage" @@ -157,7 +219,7 @@ clean: $(MAKE) -C src -f Makefile clean 2>/dev/null || true cd src && make -f makefile.mingw clean 2>/dev/null || true rm -f Bitflash-*.AppImage Bitflash-*.zip - rm -rf Bitflash-*-windows + rm -rf Bitflash-*-windows build tests: $(MAKE) -C src -f Makefile tests -- cgit v1.2.3 From 226a37d8560f0f2035c2f5342e1d685e899f7be8 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Sun, 23 Aug 2026 05:21:48 +0000 Subject: build: version this tree 1.2.18+sec, not 1.2.18 VERSION names every release artifact -- the AppImage, the windows zip and the node binary. This tree is upstream v1.2.18 plus 24 commits of our own and a payout ledger that is neither side's, so a binary built here must not be mistakable for the upstream release of that number. --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0f29081..4fdab39 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,10 @@ ROOT := $(shell pwd) NPROC := $(shell nproc 2>/dev/null || echo 2) SUDO := $(shell [ "$$(id -u)" = "0" ] && echo "" || echo "sudo") -VERSION := 1.2.18 +# Not "1.2.18". This tree is upstream v1.2.18 plus 24 commits of our own and a +# hand-merged payout ledger, so a binary built here must not be mistakable for +# the upstream release of that number -- it names every release artifact. +VERSION := 1.2.18+sec # ---- Pinned third-party sources ------------------------------------------- # -- cgit v1.2.3 From fd627b134c686e7c9afb646dc37c573c5d36fd4a Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 05:22:36 +0000 Subject: build: stop rm -rf'ing a RandomX tree the build did not create deps-randomx built into $(HOME)/RandomX and deleted that path whenever the library was missing, taking out hand-managed checkouts the build never owned. Default the build to the in-tree $(ROOT)/randomx-build, like secp256k1-build, overridable via RANDOMX_DIR and exported so src/Makefile's own fallback resolves to the same tree. As a backstop, the recipe writes a .bitflash-built marker after a successful build and refuses to delete any directory that lacks it, so a user-supplied RANDOMX_DIR pointing at a pre-existing tree is never removed. Closes #27 --- Makefile | 31 ++++++++++++++++++++++++------- src/Makefile | 4 +++- 2 files changed, 27 insertions(+), 8 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 9f97b73..83a2c73 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,17 @@ APPIMAGETOOL_SHA256 := ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3c # ---- Linux ---------------------------------------------------------------- +# RandomX used to build in $(HOME)/RandomX, and deps-randomx would rm -rf that +# path whenever the library was missing -- deleting a tree the build did not +# create and does not own (issue #27; a hand-managed pinned checkout there is +# what this machine's miners build against). The default is now in-tree, like +# secp256k1-build. A host that deliberately keeps RandomX elsewhere can set +# RANDOMX_DIR=... explicitly; the recipe below will still never delete a +# directory that lacks the marker file this build writes after a successful +# build. Exported so src/Makefile's own RANDOMX_DIR ?= picks the same tree. +RANDOMX_DIR ?= $(ROOT)/randomx-build +export RANDOMX_DIR + linux: deps-linux $(MAKE) -C src -f Makefile -j$(NPROC) strip src/bitflash @@ -109,19 +120,25 @@ deps-secp256k1: fi deps-randomx: - @if [ ! -f $(HOME)/RandomX/build/librandomx.a ]; then \ + @if [ ! -f $(RANDOMX_DIR)/build/librandomx.a ]; then \ + if [ -d $(RANDOMX_DIR) ] && [ ! -f $(RANDOMX_DIR)/.bitflash-built ]; then \ + echo "ERROR: $(RANDOMX_DIR) exists but was not created by this build"; \ + echo " refusing to rm -rf it -- remove it yourself or set RANDOMX_DIR"; \ + exit 1; \ + fi; \ echo "==> building RandomX"; \ - rm -rf $(HOME)/RandomX; \ - git init -q $(HOME)/RandomX; \ - cd $(HOME)/RandomX && \ + rm -rf $(RANDOMX_DIR); \ + git init -q $(RANDOMX_DIR); \ + cd $(RANDOMX_DIR) && \ git remote add origin $(RANDOMX_REPO) && \ git fetch -q --depth 1 origin $(RANDOMX_COMMIT) && \ git checkout -q --detach FETCH_HEAD && \ test "$$(git rev-parse HEAD)" = "$(RANDOMX_COMMIT)" && \ echo "==> RandomX pinned at $(RANDOMX_COMMIT)" && \ - mkdir -p $(HOME)/RandomX/build; \ - cd $(HOME)/RandomX/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \ - make -j$(NPROC) randomx; \ + mkdir -p $(RANDOMX_DIR)/build && \ + cd $(RANDOMX_DIR)/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \ + make -j$(NPROC) randomx && \ + touch $(RANDOMX_DIR)/.bitflash-built && \ echo "==> RandomX done"; \ else \ echo "==> RandomX already built"; \ diff --git a/src/Makefile b/src/Makefile index 1bc3ae8..2c6d304 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,9 @@ FUZZ_CXX ?= clang++ SECP_INC ?= /usr/local/include SECP_LIB ?= /usr/local/lib -RANDOMX_DIR ?= $(HOME)/RandomX +# The root Makefile exports RANDOMX_DIR (default: /randomx-build, built +# by deps-randomx). This fallback only applies when src/ is built standalone. +RANDOMX_DIR ?= $(abspath $(CURDIR)/..)/randomx-build IMGUI_DIR = imgui -- cgit v1.2.3 From 34cb6e65f171251ad331bdd67f33511904f36fb2 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 05:23:05 +0000 Subject: build: ask apt for libboost-dev, and update the package lists first libboost-system-dev is gone from Ubuntu 26.04 -- Boost.System has been header-only since 1.69, and this tree only includes two boost headers and links no boost library. The recipe also installed without an apt-get update, so a fresh image failed on stale or empty lists. Closes #28 --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 83a2c73..0eec4c2 100644 --- a/Makefile +++ b/Makefile @@ -89,11 +89,17 @@ linux-node: deps-linux deps-linux: deps-apt deps-secp256k1 deps-randomx +# libboost-dev, not libboost-system-dev: Boost.System has been header-only +# since 1.69 and Ubuntu 26.04 (resolute) no longer ships the -system package. +# This tree only includes two boost headers and links no boost library. The +# apt-get update comes first: a fresh image's package lists are empty, and +# install then fails on the first name it cannot find. deps-apt: @if command -v apt-get >/dev/null 2>&1; then \ + $(SUDO) apt-get update; \ $(SUDO) apt-get install -y build-essential cmake git pkg-config autoconf \ libtool libssl-dev libdb5.3++-dev libsodium-dev nlohmann-json3-dev \ - libboost-system-dev libglfw3-dev libgl-dev python3-pil clang; \ + libboost-dev libglfw3-dev libgl-dev python3-pil clang; \ else \ echo "Not an apt system — install: g++ cmake git autoconf libtool"; \ echo " libssl libdb++ libsodium nlohmann-json boost glfw3 opengl python3-pil"; \ -- cgit v1.2.3 From fcd0e6697038e5959df733e389124f6ccfa4a6d5 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 05:24:26 +0000 Subject: build: let appimagetool's exit status decide, and check the artefact The appimage recipe piped the tool through grep ... || true, so a failed run still ended with an unconditional "Built:" echo and make reported success with no AppImage on disk. Run appimagetool bare so its status propagates, then require the artefact to exist, be non-empty, and be newer than src/bitflash before announcing it. Closes #29 --- Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 0eec4c2..602c154 100644 --- a/Makefile +++ b/Makefile @@ -200,8 +200,17 @@ d + '/usr/share/icons/hicolor/256x256/apps/bitflash.png')" [ -z "$$path" ] && path=$$(find /usr/lib /lib -name "$$lib" 2>/dev/null | head -1); \ [ -n "$$path" ] && cp -L "$$path" $(APPDIR)/usr/lib/ && echo " bundled $$lib" || echo " missing $$lib"; \ done +# appimagetool's output used to be piped through grep ... || true, which +# discarded its exit status: the target succeeded and announced "Built:" +# even when no AppImage existed. Run the tool bare so its status decides, +# then require the artefact to exist, be non-empty, and be newer than the +# binary it was packaged from before saying so. @ARCH=x86_64 $(APPIMAGETOOL) --no-appstream $(APPDIR) \ - $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage 2>&1 | grep -E "^Built|^Error" || true + $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage + @test -s $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage || \ + { echo "ERROR: Bitflash-$(VERSION)-x86_64.AppImage missing or empty"; exit 1; } + @test $(ROOT)/Bitflash-$(VERSION)-x86_64.AppImage -nt src/bitflash || \ + { echo "ERROR: Bitflash-$(VERSION)-x86_64.AppImage is not newer than src/bitflash"; exit 1; } @echo "Built: Bitflash-$(VERSION)-x86_64.AppImage" # ---- Windows (MSYS2 UCRT64) ----------------------------------------------- -- cgit v1.2.3 From 098074193b7a3147f4ad0e0424618b52fe370026 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 16:55:03 +0000 Subject: build: quote the RandomX path so the guard cannot be stepped around The marker guard added in fd627b1 used $(RANDOMX_DIR) unquoted, so an operator-supplied value that expands to anything other than one word walked straight past it. With a glob matching two directories, `[ -d $(RANDOMX_DIR) ]` became a two-argument test, died with "unexpected operator" rather than answering, and short-circuited the && before the marker was ever looked for -- leaving `rm -rf` to run against every match. A value holding a space or a `&&` broke the outer test the same way and reported "already built", and an apostrophe made the recipe unparseable. So the commit's claim to refuse any directory lacking the marker was falsifiable. Quote every use, and reject up front the values that cannot name one directory: empty and / now refuse deliberately rather than by way of the one-argument `[ -d ]` quirk that happened to catch them, and whitespace and glob characters are refused outright because src/Makefile interpolates the same value into -I and -L unquoted, where neither survives. A relative value is refused too: it named a different directory here than in src/, and cd'ing into it made the later mkdir -p resolve against the new cwd, so the build landed in randomx-build/randomx-build/build and cmake found nothing. Verified against the recipe text as make expands it, with rm replaced by an echo, over empty, /, globs matching one and two directories, spaces, tabs, relative paths, symlinks, apostrophes, semicolons, backticks and newlines, under both dash and bash: every run either refuses with a message or passes rm exactly one argument, identical to the path the guard tested. --- Makefile | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 602c154..c891001 100644 --- a/Makefile +++ b/Makefile @@ -67,6 +67,21 @@ APPIMAGETOOL_SHA256 := ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3c # RANDOMX_DIR=... explicitly; the recipe below will still never delete a # directory that lacks the marker file this build writes after a successful # build. Exported so src/Makefile's own RANDOMX_DIR ?= picks the same tree. +# +# Every use of it below is quoted, and the recipe rejects a value that cannot +# name exactly one directory before it reaches anything destructive. Unquoted, +# the marker guard could be stepped around: a value holding a glob that matches +# two directories made `[ -d $(RANDOMX_DIR) ]` a two-argument test, which dies +# with "unexpected operator" instead of answering, so the && short-circuited, +# the guard was skipped, and the rm -rf below ran against every match. A value +# holding a space or a `&&` broke the outer test the same way and reported +# "already built". Whitespace and glob characters are refused outright rather +# than merely quoted, because src/Makefile interpolates this same value into +# -I$(RANDOMX_DIR)/src and -L$(RANDOMX_DIR)/build unquoted, where neither can +# survive. A relative value is refused rather than silently made absolute: it +# would mean two different directories to this Makefile and to src/Makefile, +# whose cwd is src/, and a command-line assignment reaches the sub-make through +# MAKEFLAGS, where it outranks anything exported from here. RANDOMX_DIR ?= $(ROOT)/randomx-build export RANDOMX_DIR @@ -126,25 +141,34 @@ deps-secp256k1: fi deps-randomx: - @if [ ! -f $(RANDOMX_DIR)/build/librandomx.a ]; then \ - if [ -d $(RANDOMX_DIR) ] && [ ! -f $(RANDOMX_DIR)/.bitflash-built ]; then \ + @ws="$$(printf ' \t')"; \ + case "$(RANDOMX_DIR)" in \ + "") echo "ERROR: RANDOMX_DIR is empty"; exit 1 ;; \ + /) echo "ERROR: RANDOMX_DIR is /, refusing"; exit 1 ;; \ + *[$$ws]*) echo "ERROR: RANDOMX_DIR contains whitespace: $(RANDOMX_DIR)"; exit 1 ;; \ + *[*?[]*) echo "ERROR: RANDOMX_DIR contains a glob character: $(RANDOMX_DIR)"; exit 1 ;; \ + /*) ;; \ + *) echo "ERROR: RANDOMX_DIR must be an absolute path: $(RANDOMX_DIR)"; exit 1 ;; \ + esac + @if [ ! -f "$(RANDOMX_DIR)/build/librandomx.a" ]; then \ + if [ -d "$(RANDOMX_DIR)" ] && [ ! -f "$(RANDOMX_DIR)/.bitflash-built" ]; then \ echo "ERROR: $(RANDOMX_DIR) exists but was not created by this build"; \ echo " refusing to rm -rf it -- remove it yourself or set RANDOMX_DIR"; \ exit 1; \ fi; \ echo "==> building RandomX"; \ - rm -rf $(RANDOMX_DIR); \ - git init -q $(RANDOMX_DIR); \ - cd $(RANDOMX_DIR) && \ + rm -rf "$(RANDOMX_DIR)" && \ + git init -q "$(RANDOMX_DIR)" && \ + cd "$(RANDOMX_DIR)" && \ git remote add origin $(RANDOMX_REPO) && \ git fetch -q --depth 1 origin $(RANDOMX_COMMIT) && \ git checkout -q --detach FETCH_HEAD && \ test "$$(git rev-parse HEAD)" = "$(RANDOMX_COMMIT)" && \ echo "==> RandomX pinned at $(RANDOMX_COMMIT)" && \ - mkdir -p $(RANDOMX_DIR)/build && \ - cd $(RANDOMX_DIR)/build && cmake .. -DCMAKE_BUILD_TYPE=Release && \ + mkdir -p "$(RANDOMX_DIR)/build" && \ + cd "$(RANDOMX_DIR)/build" && cmake .. -DCMAKE_BUILD_TYPE=Release && \ make -j$(NPROC) randomx && \ - touch $(RANDOMX_DIR)/.bitflash-built && \ + touch "$(RANDOMX_DIR)/.bitflash-built" && \ echo "==> RandomX done"; \ else \ echo "==> RandomX already built"; \ -- cgit v1.2.3 From 9886a4680cd669f376eec1bf18da7ad10057dd38 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 16:58:44 +0000 Subject: build: let a failed pin check decide the exit status everywhere fd627b1's message said the rewrite hardened a pin check that used `;` where it needed `&&`. It hardened one of four. Three recipes still ended their chain with `echo "==> ... done"; ` after a semicolon, so a mismatched pin failed the `test`, skipped every build step, and then ran the echo anyway -- exit 0, and make announced a pinned dependency that nothing had verified. deps-windows also had the same break after mkdir and after `make randomx`. The one the earlier message did not mention is deps-secp256k1, on the Linux path: libsecp256k1 is signature verification, so that was the worst of the three to leave reporting success on an unverified checkout. Joined each chain with && the whole way to the closing echo, in deps-secp256k1, and in both halves of deps-windows. Verified by extracting each recipe as make expands it, splitting it into logical recipe lines and running each in its own shell the way make does, with git reporting a sha that does not match the pin: all three previously exited 0 and now exit 1, and each deps-windows half fails independently rather than relying on the other. With a matching sha the recipes still exit 0, still print "done", and still write the marker. The Windows path was not executed -- there is no MSYS2 here -- so pacman was shimmed and only the shell logic below it was measured. --- Makefile | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index c891001..c5cf31c 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,12 @@ VERSION := 1.2.19+sec # resolves the object by its own hash). Bump deliberately, and rebuild and # resync before shipping the result. # +# The check has to decide the exit status, so each recipe below joins its +# commands with && the whole way to the closing echo. Ending that chain with a +# `;` meant a failed `test` only skipped the build steps: the echo still ran, +# the target still exited 0, and make announced a pinned dependency that +# nothing had verified. +# # RandomX pin is the commit this tree has been building and syncing against # (post-v2.0.1 master, 2026-05-24) -- identical to upstream's pin. # @@ -123,8 +129,8 @@ deps-apt: deps-secp256k1: @if [ ! -f /usr/local/lib/libsecp256k1.a ]; then \ echo "==> building libsecp256k1"; \ - rm -rf $(ROOT)/secp256k1-build; \ - git init -q $(ROOT)/secp256k1-build; \ + rm -rf $(ROOT)/secp256k1-build && \ + git init -q $(ROOT)/secp256k1-build && \ cd $(ROOT)/secp256k1-build && \ git remote add origin $(SECP256K1_REPO) && \ git fetch -q --depth 1 origin $(SECP256K1_COMMIT) && \ @@ -134,7 +140,7 @@ deps-secp256k1: cd $(ROOT)/secp256k1-build && ./autogen.sh && \ ./configure --enable-module-schnorrsig --enable-module-extrakeys \ --disable-shared --with-pic --disable-benchmark --disable-tests && \ - make -j$(NPROC) && $(SUDO) make install && $(SUDO) ldconfig; \ + make -j$(NPROC) && $(SUDO) make install && $(SUDO) ldconfig && \ echo "==> libsecp256k1 done"; \ else \ echo "==> libsecp256k1 already installed"; \ @@ -252,8 +258,8 @@ deps-windows: mingw-w64-ucrt-x86_64-cmake \ autoconf automake libtool @if [ ! -f deps/lib/libsecp256k1.a ]; then \ - rm -rf secp256k1-build; \ - git init -q secp256k1-build; \ + rm -rf secp256k1-build && \ + git init -q secp256k1-build && \ cd secp256k1-build && \ git remote add origin $(SECP256K1_REPO) && \ git fetch -q --depth 1 origin $(SECP256K1_COMMIT) && \ @@ -264,23 +270,23 @@ deps-windows: ./configure --prefix=$(ROOT)/deps \ --enable-module-schnorrsig --enable-module-extrakeys \ --disable-shared --with-pic --disable-benchmark --disable-tests && \ - make install; \ + make install && \ echo "==> secp256k1 done"; \ else \ echo "==> secp256k1 already built"; \ fi @if [ ! -f RandomX/build/librandomx.a ]; then \ - rm -rf RandomX; \ - git init -q RandomX; \ + rm -rf RandomX && \ + git init -q RandomX && \ cd RandomX && \ git remote add origin $(RANDOMX_REPO) && \ git fetch -q --depth 1 origin $(RANDOMX_COMMIT) && \ git checkout -q --detach FETCH_HEAD && \ test "$$(git rev-parse HEAD)" = "$(RANDOMX_COMMIT)" && \ echo "==> RandomX pinned at $(RANDOMX_COMMIT)" && \ - mkdir -p $(ROOT)/RandomX/build; \ + mkdir -p $(ROOT)/RandomX/build && \ cd $(ROOT)/RandomX/build && cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release && \ - make randomx; \ + make randomx && \ echo "==> RandomX done"; \ else \ echo "==> RandomX already built"; \ -- cgit v1.2.3 From 3d6373874f3972b776dd48e86321b1f8c78cd23b Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 16:59:30 +0000 Subject: build: say so when apt-get update fails instead of passing over it 34cb6e6 added `apt-get update;` before the install. The semicolon means a failed update does not stop the install, which is the behaviour we want -- one unreachable repository should not block an install the lists already on disk can satisfy -- but it was punctuation rather than a decision, and it was silent. The install then failed several seconds later with "unable to locate package" and nothing tied the two together. Kept it non-fatal, made it explicit with `|| echo`, and wrote the reasoning down next to it. The install itself is still the last command in the branch, so a failed install is still the target's status. Measured all four combinations with apt-get shimmed: a failed update now warns and carries on, a failed install still aborts. --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index c5cf31c..ace07d8 100644 --- a/Makefile +++ b/Makefile @@ -115,9 +115,16 @@ deps-linux: deps-apt deps-secp256k1 deps-randomx # This tree only includes two boost headers and links no boost library. The # apt-get update comes first: a fresh image's package lists are empty, and # install then fails on the first name it cannot find. +# +# A failed update is deliberately not fatal: one unreachable repository should +# not block an install the lists already on disk can satisfy. It does say so, +# though -- "unable to locate package" several seconds later is otherwise hard +# to connect back to it. The install is the last command in the branch, so its +# status is the target's, and that one does abort. deps-apt: @if command -v apt-get >/dev/null 2>&1; then \ - $(SUDO) apt-get update; \ + $(SUDO) apt-get update || \ + echo " warning: apt-get update failed, using the package lists on disk"; \ $(SUDO) apt-get install -y build-essential cmake git pkg-config autoconf \ libtool libssl-dev libdb5.3++-dev libsodium-dev nlohmann-json3-dev \ libboost-dev libglfw3-dev libgl-dev python3-pil clang; \ -- cgit v1.2.3