From aa1851dd6ac1299c9b3d312abeab9eda00906c30 Mon Sep 17 00:00:00 2001 From: Krystie Date: Wed, 24 Jun 2026 18:21:04 -0700 Subject: [PATCH] distribute: wait for daemon .deb before Docker Hub build The Dockerfile in packaging/docker/ downloads the daemon .deb from the release URL during the build. On tag-push, the release record is created immediately but the .deb asset gets uploaded a few seconds to minutes later by the build job. Race condition seen on v5.9.24 distribute run #24 (2026-06-24 01:10 UTC): - Workflow fired on tag push - Docker Hub job started step 5 'Build and push' immediately - Dockerfile's curl returned 404 for the .deb - Job failed in 18 seconds; release .deb was uploaded ~8 min later AUR and WinGet jobs already had this wait step; Docker Hub was the only one missing it. Added the same pattern (poll for URL reachability up to 30 * 20s = 10 min). --- .github/workflows/distribute.yml | 20 +++++++++++++++++ CMakeLists.txt | 15 ++++++++++++- src/clientversion.h | 2 +- src/init.cpp | 38 ++++++++++++++++++++++++++++---- 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/.github/workflows/distribute.yml b/.github/workflows/distribute.yml index 618c615..fd23f31 100644 --- a/.github/workflows/distribute.yml +++ b/.github/workflows/distribute.yml @@ -63,6 +63,26 @@ jobs: fi echo "$DOCKERHUB_TOKEN" | docker login -u samiahmed7777 --password-stdin + - name: Wait for release artifacts + run: | + # The Dockerfile downloads the daemon .deb from the release URL. + # On tag-push the release is created first, but the assets get + # uploaded a few seconds/minutes later by the build job — without + # this wait, the Docker build races and fails with curl 22 / 404 + # (saw this on v5.9.24 run #24, dist #24, Docker Hub job + # step #5 — release was published 8 min after the workflow fired). + for i in {1..30}; do + URL="https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}/cryptographic-triangles-daemon_${VERSION}_amd64.deb" + if curl -fsSL --head "$URL" >/dev/null 2>&1; then + echo "✓ Release .deb available: $URL" + exit 0 + fi + echo " waiting for release v${VERSION} daemon .deb... ($i/30)" + sleep 20 + done + echo "::error::Release v${VERSION} daemon .deb never became available after 10 minutes" + exit 1 + - name: Build and push run: | if [ -z "$DOCKERHUB_TOKEN" ]; then exit 0; fi diff --git a/CMakeLists.txt b/CMakeLists.txt index e29ae2f..9fb7b2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,20 @@ option(USE_IPV6 "Enable IPv6 support" ON) option(USE_QRCODE "Enable QR code generation via libqrencode" OFF) option(USE_DBUS "Enable D-Bus notifications (Linux only)" ON) option(USE_ZMQ "Enable ZMQ publisher support" OFF) -option(USE_TOR_EMBEDDED "Enable embedded Tor library linking" OFF) +# Triangles is Tor-native. Tor is REQUIRED — disabling it at build time is +# not a supported configuration. The 2026-06-23 DNS2 clearnet-fork incident +# (5+ days on a parallel chain because someone flipped -notor=1 for +# troubleshooting and never reverted it) motivated this. We keep the option +# for legacy recovery workflows, but default it ON and abort the build if +# anyone explicitly disables it. +option(USE_TOR_EMBEDDED "Enable embedded Tor library linking" ON) +if(DEFINED USE_TOR_EMBEDDED AND NOT USE_TOR_EMBEDDED) + message(FATAL_ERROR + "USE_TOR_EMBEDDED=OFF is not supported. Triangles is Tor-native. " + "If you need clearnet mode for bootstrap recovery, build with " + "USE_TOR_EMBEDDED=ON and pass -notor=1 -recovery-mode=1 at runtime " + "instead.") +endif() option(USE_O3 "Use -O3 optimization instead of -O2" OFF) option(ENABLE_PIE "Build position-independent executables" OFF) option(ENABLE_STATIC "Prefer static linking (Linux release builds)" OFF) diff --git a/src/clientversion.h b/src/clientversion.h index 22e8751..d70134f 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -8,7 +8,7 @@ // These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 5 #define CLIENT_VERSION_MINOR 9 -#define CLIENT_VERSION_REVISION 24 +#define CLIENT_VERSION_REVISION 25 #define CLIENT_VERSION_BUILD 0 // Converts the parameter X to a string after macro replacement on X has been performed. diff --git a/src/init.cpp b/src/init.cpp index 289f0e0..1e72eec 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -413,6 +413,21 @@ bool AppInit(int argc, char* argv[]) } ReadConfigFile(mapArgs, mapMultiArgs); + // AUDIT: If notorious=1 or -notor was set in triangles.conf, scream + // loudly. This is the silent path that put DNS2 on a 5+ day clearnet + // fork in 2026-06-23 — operator flipped it for troubleshooting, never + // reverted it, and the daemon happily started in clearnet-only mode. + // We refuse to proceed unless -recovery-mode=1 is ALSO set, even if + // the flag was set in the config file rather than on the command line. + if (mapArgs.count("-notor") && !GetBoolArg("-recovery-mode", false)) { + return InitError(strprintf(_( + "-notor=1 found in triangles.conf or command line. Triangles is " + "Tor-native; running without Tor is unsafe and produces silent " + "clearnet forks (see 2026-06-23 DNS2 incident). If this is an " + "explicit recovery operation, pass -recovery-mode=1 on the command " + "line (in addition to the config file setting) to acknowledge."))); + } + if (mapArgs.count("-?") || mapArgs.count("--help")) { // First part of help message is specific to trianglesd / RPC client @@ -1496,11 +1511,26 @@ bool AppInit2() fUseUPnP = false; #endif } else if (GetBoolArg("-notor", false)) { - // -notor: user explicitly disabled Tor. Allow the daemon to start - // in clearnet-only mode (useful for diagnostics, benchmarking, and - // recovery). .onion connectivity will not be available. - printf("NOTICE: Tor disabled via -notor. Running in clearnet-only mode.\n"); + // -notor: explicit clearnet mode. Triangles is Tor-native and + // running without Tor is unsafe for normal operation — it can + // produce silent clearnet forks (see 2026-06-23 DNS2 incident, + // 5+ days on a parallel chain because -notor=1 was left on after + // troubleshooting). The flag is preserved for explicit recovery + // workflows (e.g. dumputxoset-from-clearnet when bootstrapping + // a new node) but requires an additional -recovery-mode=1 + // confirmation flag so it cannot be flipped by accident. + if (!GetBoolArg("-recovery-mode", false)) { + return InitError(strprintf(_( + "-notor requires -recovery-mode=1 confirmation. Triangles is Tor-native; " + "running without Tor is unsafe and produces silent clearnet forks. " + "If you need clearnet mode for bootstrap recovery or diagnostics, " + "pass BOTH -notor=1 -recovery-mode=1 on the command line."))); + } + printf("WARNING: Tor disabled via -notor AND -recovery-mode=1 set. " + "Running in clearnet-only mode.\n"); printf(" .onion connections will NOT be available.\n"); + printf(" This mode is for RECOVERY ONLY — exit and restart without these\n" + " flags as soon as the recovery operation completes.\n"); SetReachable(NET_IPV4, true); SetReachable(NET_IPV6, true); SetReachable(NET_TOR, false);