diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..c1a46f7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +.git +.github +build +build-* +cmake-build-* +*.dat +*.log +*.pid +*.conf +*.key +*.pem +*.sqlite +*.sqlite3 +.triangles +wallet.dat +wallet.dat.* diff --git a/.github/workflows/build-all.yml b/.github/workflows/build-all.yml index ff8fe64..5355cf2 100644 --- a/.github/workflows/build-all.yml +++ b/.github/workflows/build-all.yml @@ -8,6 +8,9 @@ on: branches: [master] workflow_dispatch: +permissions: + contents: read + jobs: test-linux-unit: # This is the canonical CI gate for unit tests. Failures here MUST block @@ -18,7 +21,7 @@ jobs: # Unit regression = blocking PR (this job). runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive @@ -85,8 +88,8 @@ jobs: if [ -x build/bin/test_chaindb_equivalence ]; then ./build/bin/test_chaindb_equivalence --log_level=test_suite else - echo "test_chaindb_equivalence not built — skipping chaindb equivalence" - exit 0 + echo "::error::test_chaindb_equivalence was not built" + exit 1 fi - name: Run unit tests @@ -110,7 +113,7 @@ jobs: # and BDB until they're fixed file-by-file. SAN_FLAGS: "-fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=undefined -fno-sanitize=alignment,signed-integer-overflow,vptr" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive @@ -168,7 +171,7 @@ jobs: UBSAN_OPTIONS: "halt_on_error=1:abort_on_error=1:print_stacktrace=1" SAN_FLAGS: "-fsanitize=address,undefined,fuzzer-no-link -fno-omit-frame-pointer -fno-sanitize-recover=undefined -fno-sanitize=alignment,signed-integer-overflow,vptr" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive @@ -263,11 +266,11 @@ jobs: echo "::error::Fuzzer produced crash/leak artifacts" exit 1 fi - exit 0 + exit "$FUZZ_EXIT" - name: Upload fuzzer artifacts on success if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: fuzz-artifacts path: build-fuzz/fuzz_artifacts/ @@ -278,11 +281,11 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: msys2/setup-msys2@v2 + - uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2 with: msystem: MINGW64 update: true @@ -320,7 +323,7 @@ jobs: -DBUILD_QT=ON \ -DBUILD_DAEMON=OFF \ -DBUILD_TESTS=OFF \ - -DUSE_UPNP=ON \ + -DUSE_UPNP=OFF \ -DUSE_QRCODE=OFF \ -DUSE_I2P_EMBEDDED=ON @@ -404,7 +407,7 @@ jobs: Get-Item "Cryptographic-Triangles-${env:VERSION}-win-x64.zip" - name: Upload artifact (portable zip) - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: windows-qt-zip path: Cryptographic-Triangles-*-win-x64.zip @@ -420,6 +423,7 @@ jobs: shell: powershell run: | $TOR_VERSION = "15.0.9" + $TOR_SHA256 = "adebc1b7c65dc1b5e471064ed17585464af6f6198c3fe5c8c9108138b59ccf65" $TOR_URL = "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-windows-x86_64-${TOR_VERSION}.tar.gz" $torPath = "tor-bundle.tar.gz" $attempts = 0 @@ -443,6 +447,10 @@ jobs: } } if (-not $downloaded) { throw "Tor bundle download failed after $maxAttempts attempts" } + $actualSha256 = (Get-FileHash -Algorithm SHA256 $torPath).Hash.ToLowerInvariant() + if ($actualSha256 -ne $TOR_SHA256) { + throw "Tor bundle SHA256 mismatch: expected $TOR_SHA256, got $actualSha256" + } New-Item -ItemType Directory -Path tor-extract -Force tar -xzf tor-bundle.tar.gz -C tor-extract New-Item -ItemType Directory -Path tor-files -Force @@ -459,23 +467,11 @@ jobs: - name: Install NSIS via MSYS2 run: pacman -S --noconfirm mingw-w64-x86_64-nsis - - name: Install NSIS inetc plugin - run: | - pacman -S --noconfirm unzip - NSIS_DIR="/mingw64/share/nsis" - cd /tmp - curl -L -o Inetc.zip "https://nsis.sourceforge.io/mediawiki/images/c/c9/Inetc.zip" - unzip -o Inetc.zip -d inetc_extract - # MSYS2 mingw64 NSIS is 64-bit, needs amd64-unicode plugin in Plugins/unicode/ - mkdir -p "$NSIS_DIR/Plugins/unicode" - cp inetc_extract/Plugins/amd64-unicode/INetC.dll "$NSIS_DIR/Plugins/unicode/" - echo "Installed 64-bit INetC.dll to $NSIS_DIR/Plugins/unicode/" - - name: Build NSIS installer run: makensis //DVERSION=$VERSION contrib/nsis/setup.nsi - name: Upload installer - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: windows-qt-setup path: contrib/nsis/Cryptographic-Triangles-*-setup.exe @@ -486,11 +482,11 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive - - uses: msys2/setup-msys2@v2 + - uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2 with: msystem: MINGW64 update: true @@ -516,7 +512,7 @@ jobs: -DBUILD_DAEMON=ON \ -DBUILD_CLI=ON \ -DBUILD_TESTS=OFF \ - -DUSE_UPNP=ON \ + -DUSE_UPNP=OFF \ -DUSE_I2P_EMBEDDED=ON - name: Build libtor (embedded Tor static lib) @@ -548,6 +544,7 @@ jobs: shell: powershell run: | $TOR_VERSION = "15.0.9" + $TOR_SHA256 = "adebc1b7c65dc1b5e471064ed17585464af6f6198c3fe5c8c9108138b59ccf65" $TOR_URL = "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-windows-x86_64-${TOR_VERSION}.tar.gz" $torPath = "tor-bundle.tar.gz" $attempts = 0 @@ -571,6 +568,10 @@ jobs: } } if (-not $downloaded) { throw "Tor bundle download failed after $maxAttempts attempts" } + $actualSha256 = (Get-FileHash -Algorithm SHA256 $torPath).Hash.ToLowerInvariant() + if ($actualSha256 -ne $TOR_SHA256) { + throw "Tor bundle SHA256 mismatch: expected $TOR_SHA256, got $actualSha256" + } New-Item -ItemType Directory -Path tor-extract -Force tar -xzf tor-bundle.tar.gz -C tor-extract Copy-Item -Recurse tor-extract/tor/* daemon-dist/tor/ @@ -579,7 +580,7 @@ jobs: } - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: windows-daemon path: daemon-dist/ @@ -587,7 +588,7 @@ jobs: build-linux-qt: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive @@ -621,7 +622,7 @@ jobs: -DBUILD_QT=ON \ -DBUILD_DAEMON=OFF \ -DBUILD_TESTS=OFF \ - -DUSE_UPNP=ON \ + -DUSE_UPNP=OFF \ -DUSE_I2P_EMBEDDED=ON - name: Build libtor (embedded Tor static lib) @@ -646,6 +647,7 @@ jobs: run: | set -euo pipefail TOR_VERSION="15.0.9" + TOR_SHA256="7ea13e14cddafb36c6347a9c4f4e639f6010364c16acfd519157c29e226277f2" # Resilient download: archive.torproject.org occasionally times out # from CI egress (observed 2026-07-03: macOS job exit code 6 after # exactly 30s of curl hang). Retries + --fail-with-body surface the @@ -654,6 +656,7 @@ jobs: --retry 3 --retry-delay 5 --retry-connrefused --retry-all-errors \ "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-linux-x86_64-${TOR_VERSION}.tar.gz" \ -o tor-bundle.tar.gz + printf '%s %s\n' "$TOR_SHA256" tor-bundle.tar.gz | sha256sum --check --strict - mkdir -p tor-extract && tar -xzf tor-bundle.tar.gz -C tor-extract PKG="cryptographic-triangles_${VERSION}_amd64" @@ -723,7 +726,7 @@ jobs: dpkg-deb --build ${PKG} - name: Upload .deb - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: linux-qt-deb path: cryptographic-triangles_*_amd64.deb @@ -731,7 +734,7 @@ jobs: build-linux-daemon: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive @@ -765,7 +768,7 @@ jobs: -DBUILD_DAEMON=ON \ -DBUILD_CLI=ON \ -DBUILD_TESTS=OFF \ - -DUSE_UPNP=ON \ + -DUSE_UPNP=OFF \ -DUSE_I2P_EMBEDDED=ON - name: Build libtor (embedded Tor static lib) @@ -794,7 +797,7 @@ jobs: run: bash scripts/ci/package-linux-daemon.sh "${VERSION}" - name: Upload .deb - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: linux-daemon-deb path: cryptographic-triangles-daemon_*_amd64.deb @@ -802,7 +805,7 @@ jobs: build-macos: runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: submodules: recursive @@ -834,7 +837,7 @@ jobs: -DBUILD_QT=ON \ -DBUILD_DAEMON=OFF \ -DBUILD_TESTS=OFF \ - -DUSE_UPNP=ON \ + -DUSE_UPNP=OFF \ -DUSE_I2P_EMBEDDED=ON \ -DBOOST_ROOT=/opt/homebrew/opt/boost \ -DBDB_INCLUDE_PATH=/opt/homebrew/opt/berkeley-db@5/include \ @@ -861,18 +864,6 @@ jobs: ZLIB_DIR=/opt/homebrew/opt/zlib \ bash src/tor/build-libtor.sh - - name: Build libtor (embedded Tor static lib) - # macOS Qt GUI also transitively links -ltor via triangles_common. - # macOS Qt is built with @rpath embedded, so libtor needs to be - # at the configured TOR_SOURCE_ROOT location. - run: | - brew install libevent openssl@3 autoconf automake libtool zlib - export PATH="/opt/homebrew/opt/automake/bin:/opt/homebrew/opt/libtool/bin:$PATH" - LIBEVENT_DIR=/opt/homebrew/opt/libevent \ - OPENSSL_DIR=/opt/homebrew/opt/openssl@3 \ - ZLIB_DIR=/opt/homebrew/opt/zlib \ - bash src/tor/build-libtor.sh - - name: Build libi2pd (embedded I2P static lib) # HOMEBREW=1 tells the i2pd Makefile to use Homebrew paths. run: HOMEBREW=1 bash src/i2p/build-libi2pd.sh @@ -929,10 +920,12 @@ jobs: run: | set -euo pipefail TOR_VERSION="15.0.9" + TOR_SHA256="8ab84587b09b0053e85a137969b501744fa14640aa126af6e36997189950d254" curl -fSL --connect-timeout 15 --max-time 120 \ --retry 3 --retry-delay 5 --retry-connrefused --retry-all-errors \ "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/tor-expert-bundle-macos-aarch64-${TOR_VERSION}.tar.gz" \ -o tor-bundle.tar.gz + printf '%s %s\n' "$TOR_SHA256" tor-bundle.tar.gz | shasum -a 256 --check - mkdir -p tor-extract && tar -xzf tor-bundle.tar.gz -C tor-extract APP=$(find build/bin -name "*.app" -maxdepth 1 | head -1) mkdir -p "$APP/Contents/MacOS/tor" @@ -952,7 +945,7 @@ jobs: "Cryptographic-Triangles-v${VERSION}-macos-arm64.dmg" - name: Upload DMG - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: macos-arm64-dmg path: "*.dmg" @@ -968,7 +961,7 @@ jobs: run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: path: artifacts @@ -990,7 +983,7 @@ jobs: ls -la release/ - name: Create Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: files: release/* generate_release_notes: true diff --git a/Dockerfile b/Dockerfile index 94d2f36..5264d9d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,38 +1,83 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 AS builder -LABEL maintainer="Cryptographic Triangles Team" -LABEL description="Cryptographic Triangles (TRI) headless daemon" -LABEL version="6.1.7" +ARG DEBIAN_FRONTEND=noninteractive +ARG SOURCE_DATE_EPOCH=1700000000 +ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} RUN apt-get update && apt-get install -y --no-install-recommends \ + autoconf \ + automake \ + build-essential \ ca-certificates \ - curl \ - libssl3 \ - libdb5.3++ \ - libboost-system1.74.0 \ - libboost-filesystem1.74.0 \ - libboost-program-options1.74.0 \ - libboost-thread1.74.0 \ - libboost-chrono1.74.0 \ - libevent-2.1-7 \ - libminiupnpc17 \ - tor \ + cmake \ + libboost-all-dev \ + libdb++-dev \ + libevent-dev \ + libleveldb-dev \ + liblz4-dev \ + liblzma-dev \ + libminiupnpc-dev \ + librocksdb-dev \ + libsnappy-dev \ + libsqlite3-dev \ + libssl-dev \ + libtool \ + libzstd-dev \ + ninja-build \ + pkg-config \ + zlib1g-dev \ && rm -rf /var/lib/apt/lists/* -ARG VERSION=5.7.6 -RUN curl -L -o /usr/local/bin/trianglesd \ - https://github.com/SamiAhmed7777/triangles_v5/releases/download/v${VERSION}/Cryptographic-Triangles-v${VERSION}-linux-x64-daemon \ - && chmod +x /usr/local/bin/trianglesd +WORKDIR /src +COPY . . + +RUN test -s src/secp256k1/CMakeLists.txt \ + && test -s src/tor/tor-src/configure.ac + +RUN LIBEVENT_DIR=/usr OPENSSL_DIR=/usr ZLIB_DIR=/usr \ + bash src/tor/build-libtor.sh + +RUN cmake -S . -B build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_QT=OFF \ + -DBUILD_DAEMON=ON \ + -DBUILD_CLI=ON \ + -DBUILD_TESTS=OFF \ + -DUSE_UPNP=OFF \ + -DUSE_I2P_EMBEDDED=OFF \ + && cmake --build build --parallel 2 + +RUN install -D -m 0755 build/bin/trianglesd /opt/triangles/bin/trianglesd \ + && install -D -m 0755 build/bin/triangles-cli /opt/triangles/bin/triangles-cli \ + && mkdir -p /opt/triangles/rootfs \ + && { ldd /opt/triangles/bin/trianglesd; ldd /opt/triangles/bin/triangles-cli; } \ + | awk '/=> \// {print $3} /^\// {print $1}' \ + | sort -u \ + | while IFS= read -r library; do \ + cp --parents -L "${library}" /opt/triangles/rootfs; \ + done + +FROM ubuntu:24.04 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \ + && rm -rf /var/lib/apt/lists/* \ + && groupadd --gid 10001 triangles \ + && useradd --uid 10001 --gid triangles --home-dir /var/lib/triangles \ + --no-create-home --shell /usr/sbin/nologin triangles \ + && install -d -m 0700 -o triangles -g triangles /var/lib/triangles + +COPY --from=builder /opt/triangles/rootfs/ / +COPY --from=builder /opt/triangles/bin/ /usr/local/bin/ +RUN ldconfig -RUN useradd -m -s /bin/bash triangles USER triangles -WORKDIR /home/triangles +WORKDIR /var/lib/triangles -RUN mkdir -p .triangles +EXPOSE 24112 +VOLUME ["/var/lib/triangles"] +STOPSIGNAL SIGTERM -EXPOSE 24112 19112 - -VOLUME ["/home/triangles/.triangles"] - -ENTRYPOINT ["trianglesd"] -CMD ["-printtoconsole", "-txindex=1"] +ENTRYPOINT ["/usr/local/bin/trianglesd"] +CMD ["-datadir=/var/lib/triangles", "-printtoconsole", "-upnp=0", "-rest=0", "-rpcbind=127.0.0.1"] diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..cb11d4c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,66 @@ +# Security Policy + +Triangles is wallet software and should be treated as security-sensitive. Do +not use an experimental build to custody funds that you cannot afford to lose. + +## Reporting a vulnerability + +Please report suspected vulnerabilities through a private GitHub security +advisory for this repository. Do not include secrets, wallet files, seed +phrases, private keys, or live RPC credentials in an issue, pull request, log, +or test fixture. + +Include the affected commit, platform, reproduction steps, impact, and a +minimal proof of concept when possible. Public disclosure should wait until a +fix is available and users have had a reasonable upgrade window. + +## Deployment boundary + +The JSON-RPC protocol uses HTTP Basic authentication and does not provide TLS. +Keep it on loopback or a private Unix host boundary. Never expose the RPC port +directly to the internet. + +For application integrations: + +- Run `trianglesd` as a dedicated, unprivileged operating-system user. +- Bind RPC explicitly to loopback with `rpcbind=127.0.0.1`. +- Use a unique random RPC username and password stored in a mode `0600` file. +- Set `rpcallowip=127.0.0.1` and an exact `rpcallowmethod` list. +- Keep `rest=0`, `upnp=0`, and wallet RPC methods disabled unless required. +- Do not pass RPC passwords on a process command line. +- Separate the node wallet and files from the integrating application's user. +- Start new integrations with an empty wallet and no production funds. + +The container image runs as UID/GID `10001` and intentionally does not create +or print RPC credentials. Mount a private `/var/lib/triangles` volume containing +an owner-only `triangles.conf`; startup without valid RPC credentials fails with +a nonzero exit status. Do not provide wallet or RPC secrets through Docker +command arguments or environment variables. + +Set `listen=0` when inbound P2P is unnecessary. When inbound peers are needed, +use `bind=
` and publish only the P2P port. The RPC port must remain +unpublished and loopback-bound. + +Remote snapshot bootstrap is opt-in. A snapshot is accepted only when its file +hash and checkpoint are compiled into the client. Treat changes to snapshot +hashes, checkpoints, seed hosts, release keys, submodule revisions, and CI +workflows as security-critical review items. + +## Wallet handling + +- Encrypt wallets before funding them. +- Record the HD mnemonic offline and test recovery on an isolated machine. +- Keep multiple offline backups; filesystem permissions are not a backup. +- Encrypting the live wallet does not retroactively encrypt old copies, + migration backups, snapshots, or filesystem remnants. Inventory and protect + every pre-encryption copy as if it contains plaintext private keys. +- Never share a seed phrase with support personnel or paste it into an RPC call. +- Stop the node and investigate any wallet database integrity error rather than + attempting to continue with a partially loaded wallet. + +## Build trust + +Build from a reviewed commit, initialize submodules at the recorded revisions, +and verify release signatures against a key fingerprint obtained through an +independent trusted channel. A valid signature proves key possession, not the +identity of the key owner. diff --git a/contrib/nsis/setup.nsi b/contrib/nsis/setup.nsi index fc24283..fddbfee 100644 --- a/contrib/nsis/setup.nsi +++ b/contrib/nsis/setup.nsi @@ -31,10 +31,6 @@ RequestExecutionLevel user !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_DIRECTORY - -; Bootstrap page -Page custom BootstrapPage - !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH @@ -43,34 +39,6 @@ Page custom BootstrapPage !insertmacro MUI_LANGUAGE "English" -; Bootstrap selection variable -Var BootstrapChoice - -; Bootstrap page function -Function BootstrapPage - !insertmacro MUI_HEADER_TEXT "Blockchain Sync" "Choose how to synchronize the blockchain" - - nsDialogs::Create 1018 - Pop $0 - - ${NSD_CreateLabel} 0 10u 100% 20u "The Triangles blockchain requires ~1GB of data. Choose sync method:" - Pop $0 - - ${NSD_CreateRadioButton} 10u 40u 100% 12u "Download bootstrap (~1.3GB) — Recommended (fast)" - Pop $1 - ${NSD_Check} $1 - - ${NSD_CreateRadioButton} 10u 60u 100% 12u "Sync from network — Slow (may take days)" - Pop $2 - - ${NSD_CreateLabel} 10u 80u 100% 30u "Bootstrap will download a recent blockchain snapshot, saving hours or days of sync time. Network bandwidth required: ~1.3GB." - Pop $0 - - nsDialogs::Show - - ${NSD_GetState} $1 $BootstrapChoice -FunctionEnd - Section "Install" SetOutPath "$INSTDIR" @@ -84,25 +52,6 @@ Section "Install" ; Create data directory CreateDirectory "$APPDATA\Triangles" - ; Download blockchain bootstrap if selected - ${If} $BootstrapChoice == ${BST_CHECKED} - DetailPrint "Downloading blockchain bootstrap..." - inetc::get /CAPTION "Downloading Blockchain" /CANCELTEXT "Skip" \ - "http://bootstrap.cryptographic-triangles.org/tri-blockchain.tar.gz" \ - "$TEMP\tri-blockchain.tar.gz" /END - Pop $0 - ${If} $0 == "OK" - DetailPrint "Extracting blockchain..." - nsExec::ExecToLog '"$INSTDIR\7z.exe" x "$TEMP\tri-blockchain.tar.gz" -o"$TEMP" -y' - nsExec::ExecToLog '"$INSTDIR\7z.exe" x "$TEMP\tri-blockchain.tar" -o"$APPDATA\Triangles" -y' - Delete "$TEMP\tri-blockchain.tar.gz" - Delete "$TEMP\tri-blockchain.tar" - DetailPrint "Blockchain bootstrap installed!" - ${Else} - DetailPrint "Bootstrap download failed or skipped — will sync from network" - ${EndIf} - ${EndIf} - ; Uninstaller WriteUninstaller "$INSTDIR\uninstall.exe" diff --git a/scripts/ci/build-rocksdb.sh b/scripts/ci/build-rocksdb.sh index 515bafa..0885d8a 100755 --- a/scripts/ci/build-rocksdb.sh +++ b/scripts/ci/build-rocksdb.sh @@ -21,6 +21,7 @@ set -euo pipefail ROCKSDB_VERSION="${ROCKSDB_VERSION:-8.9.1}" ROCKSDB_TAG="v${ROCKSDB_VERSION}" +ROCKSDB_COMMIT="${ROCKSDB_COMMIT:-49ce8a1064dd1ad89117899839bf136365e49e79}" INSTALL_PREFIX="${INSTALL_PREFIX:-/usr/local}" JOBS="${JOBS:-$(nproc)}" @@ -34,6 +35,12 @@ git clone --depth 1 --branch "${ROCKSDB_TAG}" \ cd "${WORKDIR}/rocksdb" +ACTUAL_COMMIT="$(git rev-parse HEAD)" +if [ "${ACTUAL_COMMIT}" != "${ROCKSDB_COMMIT}" ]; then + echo "!!! RocksDB ${ROCKSDB_TAG} resolved to ${ACTUAL_COMMIT}, expected ${ROCKSDB_COMMIT}" >&2 + exit 1 +fi + # Shared library only — Triangles links dynamically. Statically linking # rocksdb.a would also work but balloons the daemon binary by ~50 MB. make -j"${JOBS}" shared_lib PORTABLE=1 USE_RTTI=1 \ @@ -83,4 +90,4 @@ fi echo ">>> RocksDB ${ROCKSDB_TAG} installed to ${INSTALL_PREFIX}" echo ">>> - library: ${INSTALL_PREFIX}/lib/librocksdb.so.${ROCKSDB_VERSION}" echo ">>> - headers: ${INSTALL_PREFIX}/include/rocksdb/version.h" -ls -l "${INSTALL_PREFIX}/lib/librocksdb.so"* "${INSTALL_PREFIX}/include/rocksdb/version.h" \ No newline at end of file +ls -l "${INSTALL_PREFIX}/lib/librocksdb.so"* "${INSTALL_PREFIX}/include/rocksdb/version.h" diff --git a/scripts/ci/package-linux-daemon.sh b/scripts/ci/package-linux-daemon.sh index eba8539..895199e 100755 --- a/scripts/ci/package-linux-daemon.sh +++ b/scripts/ci/package-linux-daemon.sh @@ -15,6 +15,7 @@ set -euo pipefail VERSION="${1:-0.0.0}" PKG="cryptographic-triangles-daemon_${VERSION}_amd64" TOR_VERSION="${TOR_VERSION:-15.0.9}" +TOR_SHA256="${TOR_SHA256:-7ea13e14cddafb36c6347a9c4f4e639f6010364c16acfd519157c29e226277f2}" echo ">>> Building .deb for triangles ${VERSION}" @@ -39,6 +40,7 @@ if [ ! -f "${TOR_TARBALL}" ]; then "https://archive.torproject.org/tor-package-archive/torbrowser/${TOR_VERSION}/${TOR_TARBALL}" \ -o "${TOR_TARBALL}" fi +printf '%s %s\n' "${TOR_SHA256}" "${TOR_TARBALL}" | sha256sum --check --strict - mkdir -p tor-extract tar -xzf "${TOR_TARBALL}" -C tor-extract @@ -107,10 +109,35 @@ Wants=network-online.target [Service] Type=simple +User=triangles +Group=triangles +UMask=0077 +Environment=HOME=/var/lib/triangles Environment=LD_LIBRARY_PATH=/usr/lib/cryptographic-triangles/lib -ExecStart=/usr/lib/cryptographic-triangles/trianglesd +StateDirectory=triangles +StateDirectoryMode=0700 +WorkingDirectory=/var/lib/triangles +ExecStart=/usr/lib/cryptographic-triangles/trianglesd -datadir=/var/lib/triangles -conf=/etc/triangles/triangles.conf -printtoconsole Restart=on-failure RestartSec=10 +NoNewPrivileges=true +PrivateDevices=true +PrivateTmp=true +ProtectClock=true +ProtectControlGroups=true +ProtectHome=true +ProtectHostname=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectSystem=strict +ReadWritePaths=/var/lib/triangles +CapabilityBoundingSet= +LockPersonality=true +MemoryDenyWriteExecute=true +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 +RestrictRealtime=true +RestrictSUIDSGID=true +SystemCallArchitectures=native [Install] WantedBy=multi-user.target @@ -127,11 +154,41 @@ Description: Cryptographic Triangles daemon + CLI with integrated Tor Tor, and systemd service. No external dependencies required. Section: finance Priority: optional +Depends: adduser CTRL # DEBIAN/postinst cat > "${PKG}/DEBIAN/postinst" << 'POST' #!/bin/bash +set -e + +if ! getent group triangles >/dev/null; then + addgroup --system triangles +fi +if ! id triangles >/dev/null 2>&1; then + adduser --system --ingroup triangles --home /var/lib/triangles \ + --no-create-home --disabled-login triangles +fi + +install -d -m 0700 -o triangles -g triangles /var/lib/triangles +install -d -m 0750 -o root -g triangles /etc/triangles + +if [ ! -e /etc/triangles/triangles.conf ]; then + RPC_PASSWORD="$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | od -An -tx1 | tr -d ' \n')" + CONFIG_TMP="$(mktemp)" + trap 'rm -f "${CONFIG_TMP}"' EXIT + cat > "${CONFIG_TMP}" << CONF +server=1 +rpcuser=trianglesrpc +rpcpassword=${RPC_PASSWORD} +rpcbind=127.0.0.1 +rpcallowip=127.0.0.1 +rest=0 +upnp=0 +CONF + install -m 0640 -o root -g triangles "${CONFIG_TMP}" /etc/triangles/triangles.conf +fi + systemctl daemon-reload echo "" echo "Cryptographic Triangles daemon + CLI installed."