diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml index 6a1f67c..87b5cd9 100644 --- a/.gitea/workflows/deploy.yaml +++ b/.gitea/workflows/deploy.yaml @@ -20,6 +20,7 @@ on: - "**.md" - .gitea/workflows/ci.yml - .gitea/workflows/bench.yaml + - .gitea/workflows/release.yaml workflow_dispatch: inputs: mode: diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml new file mode 100644 index 0000000..db3c54d --- /dev/null +++ b/.gitea/workflows/release.yaml @@ -0,0 +1,78 @@ +--- +# Release binaries for independent miners (quantus/miner#27). +# +# Pushing a tag `v-lair.` builds the miner and the bench +# harness on the cuda-13.0 runner (Fedora 43 like the mining hosts, and the +# only runner with nvcc, so the binary carries the sm_86/sm_89/sm_120 cubins +# and PTX), records what was built, and publishes a Gitea release with the +# binaries, their checksums and the build report attached. The tag's commit +# is embedded in `--version` so a downloaded binary identifies itself. +# +# Deploying to the fleet is deploy.yaml's job and follows main; a release is +# only a public snapshot and changes nothing on the hosts. +name: release + +on: + push: + tags: ["v*-lair.*"] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: cuda-13.0 + steps: + - uses: actions/checkout@v4 + - name: build quantus-miner and quantus-bench + env: + MINER_BUILD_SHA: ${{ github.sha }} + MINER_CUDA_REQUIRE: "1" + run: | + set -euo pipefail + cargo build --release --locked -p miner-cli -p bench-harness + ./target/release/quantus-miner --version + ./target/release/quantus-bench --version || true + - name: package + run: | + set -euo pipefail + tag="${GITHUB_REF_NAME}" + dir="quantus-miner-${tag}-linux-x86_64" + mkdir -p "dist/${dir}" + cp target/release/quantus-miner target/release/quantus-bench "dist/${dir}/" + cp LICENSE "dist/${dir}/" + { + echo "quantus-miner ${tag}" + echo "commit: ${GITHUB_SHA}" + echo "built: $(date -u +%Y-%m-%dT%H:%M:%SZ) on $(source /etc/os-release && echo "$PRETTY_NAME"), $(ldd --version | head -1)" + echo "cuda: $(nvcc --version | grep -oE 'release [0-9.]+' | head -1)" + echo "cubins: sm_86 sm_89 sm_120 + compute_120 PTX" + echo "version string: $(./target/release/quantus-miner --version)" + } > "dist/${dir}/BUILD.txt" + (cd dist && tar -czf "${dir}.tar.gz" "${dir}" && sha256sum "${dir}.tar.gz" > "${dir}.tar.gz.sha256") + cat "dist/${dir}/BUILD.txt" "dist/${dir}.tar.gz.sha256" + - name: publish release + run: | + set -euo pipefail + tag="${GITHUB_REF_NAME}" + dir="quantus-miner-${tag}-linux-x86_64" + api="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}" + auth="Authorization: token ${{ secrets.GITHUB_TOKEN }}" + body=$(python3 - "$tag" "dist/${dir}/BUILD.txt" "dist/${dir}.tar.gz.sha256" <<'PY' + import json, sys, pathlib + tag, build, sha = sys.argv[1], pathlib.Path(sys.argv[2]).read_text(), pathlib.Path(sys.argv[3]).read_text().strip() + text = ( + f"quantus-miner {tag}: Linux x86_64, NVIDIA RTX 30/40/50 (sm_86, sm_89, sm_120, plus PTX), " + "glibc 2.42 or newer, driver with CUDA 13.0 support.\n\n" + "No dev fee, no licence server, no telemetry. Measured rates and how to reproduce them are in the README.\n\n" + f"```\n{build}```\n\nsha256: `{sha}`\n" + ) + print(json.dumps({"tag_name": tag, "name": f"quantus-miner {tag}", "body": text, "draft": False, "prerelease": False})) + PY + ) + id=$(curl -fsS -X POST -H "$auth" -H "Content-Type: application/json" "${api}/releases" -d "$body" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])') + echo "release id ${id}" + for f in "dist/${dir}.tar.gz" "dist/${dir}.tar.gz.sha256" "dist/${dir}/BUILD.txt"; do + curl -fsS -X POST -H "$auth" "${api}/releases/${id}/assets?name=$(basename "$f")" -F "attachment=@${f}" > /dev/null + echo "attached $(basename "$f")" + done diff --git a/README.md b/README.md index df92186..2207e56 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,52 @@ High-performance external mining service for Quantus Network with support for CPU, GPU, and hybrid CPU+GPU mining. +## This fork + +Like the official miner, but fast: a native CUDA engine for NVIDIA cards, kept +bit-exact with the reference hash and measured against every other miner we +can get hold of. No dev fee, no licence server, no telemetry, solo or pool. +Apache-2.0, like upstream. + +**Measured hashrate**, three interleaved 30-second rounds per card at the +enforced power cap, memory clock locked at 810 MHz, CUDA 13.0 driver 580: + +| card | power cap | this fork | upstream `--cuda-gpu` | quantusminer.com qpow-cuda 1.0.7 | quanpool-miner 6.2.4 (5% fee) | +|---|---|---|---|---|---| +| RTX 5090 | 400 W | **1104 MH/s** | 944 | 1171 | 1234 (1172 after fee) | +| RTX 4090 | 250 W | **711 MH/s** | | | | +| RTX 3060 | 130 W | **141 MH/s** | | | | + +The 5090 column was measured on the same card in the same session +(2026-09-13); the closed pool binaries were run in benchmark mode only. How +the pool kernels get their remaining edge, and what has been tried, is +written up in [issue #27](https://git.lair.cafe/quantus/miner/issues/27). + +**Binaries** are on the [releases page](https://git.lair.cafe/quantus/miner/releases): +one Linux x86_64 `quantus-miner` carrying cubins for sm_86 (RTX 30), sm_89 +(RTX 40) and sm_120 (RTX 50) plus PTX for anything newer, built on Fedora 43 +(glibc 2.42 or newer), and `quantus-bench`, the measurement harness. Nothing +is compiled at run time; the driver needs CUDA 13.0 support (580.x). + +**Reproduce the numbers.** `quantus-bench` pins the power limit it expects, +warms up, reports the median of timed windows with their spread, and checks +GPU hashes against the CPU reference for random jobs: + +```bash +# hashrate: median of 5 x 30 s windows, one worker thread per card +./quantus-bench --duration-secs 30 --runs 5 --workers 1 --expect-power-limit 400 + +# parity: 2000 random jobs, every found hash recomputed on the CPU +./quantus-bench --duration-secs 3 --runs 1 --parity-jobs 2000 +``` + +Compare builds with interleaved rounds (A, B, A, B, ...) rather than one +block of runs each: on a power-capped card, clock drift between blocks looks +like a 0.5% code change. + +**Solo mining** against your own node is the `serve` command below with the +node's auth token and certificate fingerprint; nothing else is needed. + ## Building ```bash