Skip to content

Ship simplepool as a release you can install in one line - #39

Merged
rsantacroce merged 2 commits into
mainfrom
2026-08-18-installer-release-and-daily-payouts
Aug 18, 2026
Merged

Ship simplepool as a release you can install in one line#39
rsantacroce merged 2 commits into
mainfrom
2026-08-18-installer-release-and-daily-payouts

Conversation

@rsantacroce

Copy link
Copy Markdown
Collaborator

Three things, all pointing at the same gap: simplepool was installable only if you already knew how to install it. Plus the payout cadence change.

1. A release path

  • scripts/release.sh builds a tarball; .github/workflows/release.yaml publishes one per architecture on a v* tag, with a merged SHA256SUMS.
  • The tarball is a git checkout with a prebuilt binary dropped in, not a trimmed runtime bundle. The systemd units, nginx vhost, schema.sql and the dashboard all already expect a checkout at $ROOT, so shipping that shape means the release path and the source path converge after one step instead of forking into two sets of layout assumptions.
  • release.sh refuses a dirty tree: the binary is built from the working tree while the source beside it comes from git archive, and on a dirty tree those are two different programs. --allow-dirty to override.
  • CI unpacks each tarball and runs build/simplepool --version out of it before publishing — a tarball that doesn't produce a runnable binary never becomes a release.
  • Glibc floor stated explicitly: built on Ubuntu 22.04 (2.35), recorded in each tarball's RELEASE file.

2. An installer that survives being piped

  • --from-release [tag] — downloads the published build for the machine's arch, verifies it against SHA256SUMS, unpacks. No compiler, no clone. Now the default when there's no checkout to build from; --from-source for the old behaviour.
  • curl | sudo bash could not have worked. BASH_SOURCE[0] is not a readable path when piped, so both the sudo re-exec and --help were reading a file that isn't there. Both now handled.
  • The default repo pointed at a mirror with no published releases, which would have made --from-release fail on a fresh box. Now LayerTwo-Labs/simplepool.
  • A release install skips build-essential/git but still installs the -dev packages, because those are the names that stay put across distro releases (libhiredis-dev everywhere, vs libhiredis0.14 on 22.04 and libhiredis1.1.0 on 24.04).
  • Refuses to overlay a tarball onto a git checkout — that produces a tree that is neither.

3. simplepoolctl

status / logs / config / doctor / upgrade / uninstall, reading the same /etc/simplepool/install.env the installer writes, so it needs no configuration of its own. upgrade re-runs the installer non-interactively rather than reimplementing it, so an upgrade cannot drift from a fresh install. doctor checks the things that actually break: binary runs here, addresses set, schema loaded, data dir writable by the service user, bitcoind answers getblockchaininfo, something listening on :3334.

4. Payouts run daily

As requested — but PAYOUT_INTERVAL_MS drove both the payout run and the settlement re-check of an already-broadcast batch. Setting it to 24h naively would have left a real, already-sent payout uncredited for a day, and let a missed BMM request sit unrecovered for the same. Split into three clocks:

after a tick that… next tick
did nothing, or settled cleanly PAYOUT_INTERVAL_MS24h
broadcast a batch, or is waiting on one PAYOUT_SETTLE_INTERVAL_MS — 30s
failed to broadcast, or reserve short PAYOUT_RETRY_INTERVAL_MS — 5m

Long delays are served in hops, because setTimeout wraps past ~24.8 days and would turn a monthly cadence into a spin that broadcasts every tick. payout/test/cadence.test.js pins every row of that table plus the clamp.

5. Docs

  • docs/simplepool.html — one self-contained, no-JavaScript, theme-aware page covering both modes end to end: shares, the nonce split, difficulty and vardiff, both coinbase shapes, PPS rate derivation, Thunder payouts, the four audit queries, the data model, config, and what the pool can't do.
  • RELEASING.md — the tag flow.
  • README gets an Install section; INSTALL.md Part B is reorganised into installer / deploy-script / manual.

Cutting the release after this merges

VERSION is bumped to 0.2.0, so git tag v0.2.0 && git push origin v0.2.0 publishes immediately. The release job fails a tag that disagrees with the Makefile, because the version is compiled into the binary and a release whose own --version differs from its name makes every later "which version is this box running?" answer untrustworthy.

Testing

  • make test — all 7 C suites pass
  • payout — 56/56 (14 new)
  • dashboard — 76 pass, 2 skipped, 0 fail
  • scripts/release.sh run end to end; tarball layout verified against what install.sh asserts and what the CI smoke test checks
  • docs/simplepool.html rendered and screenshotted in light and dark; no external assets, no scripts, all 21 anchors resolve, tags balanced

Two bugs found and fixed in my own code while reviewing: the installer's cleanup trap expanded a local that was out of scope by exit time, making rm -rf "" fail and take the exit status with it — every successful release install would have ended non-zero; and the setTimeout overflow above.

Not tested end to end: the installer itself has not been run on a real Linux box (no Docker daemon available locally, and it guards against non-Linux). The release download path in particular can only be exercised once a release actually exists — which is the next step after this merges.

🤖 Generated with Claude Code

rsantacroce and others added 2 commits August 18, 2026 17:49
Three things, all pointing at the same gap: simplepool was installable
only if you already knew how to install it.

**A release path.** `scripts/release.sh` builds a tarball, and
`.github/workflows/release.yaml` publishes one per architecture on a
`v*` tag with a merged SHA256SUMS. The tarball is a git checkout with a
prebuilt binary dropped in rather than a trimmed runtime bundle — the
systemd units, nginx vhost, schema.sql and dashboard all already expect
a checkout at $ROOT, so shipping that shape means the release path and
the source path converge after one step instead of forking into two
sets of layout assumptions. release.sh refuses a dirty tree: the binary
is built from the working tree while the source beside it comes from
`git archive`, and on a dirty tree those are two different programs.

**An installer that survives being piped.** `install.sh` gains
`--from-release [tag]` (now the default when there is no checkout to
build) which downloads, verifies against SHA256SUMS, and unpacks — no
compiler, no clone. `curl | sudo bash` was already the documented
one-liner but could not have worked: BASH_SOURCE[0] is not a readable
path when piped, so both the sudo re-exec and `--help` read a file that
isn't there. Also fixes the default repo, which pointed at a mirror
with no published releases.

**`simplepoolctl`.** status / logs / config / doctor / upgrade /
uninstall, reading the same /etc/simplepool/install.env the installer
writes, so it needs no configuration of its own. `upgrade` re-runs the
installer non-interactively rather than reimplementing it, so an
upgrade cannot drift from a fresh install.

Payouts move to a daily batch, as asked. The subtlety is that
PAYOUT_INTERVAL_MS drove both the payout run *and* the settlement
re-check of an already-broadcast batch, so setting it to 24h naively
would leave a real, already-sent payout uncredited for a day and let a
missed BMM request sit unrecovered for the same. Split into three
clocks — run (24h), settle (30s), retry (5m) — with nextDelayMs()
picking one from what the tick actually did. Long delays are served in
hops because setTimeout wraps past ~24.8 days and would turn a monthly
cadence into a spin.

Adds docs/simplepool.html: one self-contained no-JavaScript page
covering both modes end to end, and RELEASING.md for the tag flow.
Bumps VERSION to 0.2.0 so tagging v0.2.0 works after this merges — the
release job fails a tag that disagrees with the Makefile, since the
version is compiled into the binary.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`build-test` stalled for 29 minutes and was cancelled by hand. The log
puts it precisely: the Azure mirror `Ign`'d every entry, apt fell back
to archive.ubuntu.com, and the job sat on

    Get:5 https://archive.ubuntu.com/ubuntu noble-security InRelease

from 15:51:14 until the cancel at 16:20:01. It never reached package
download — the whole failure was the index refresh.

`apt-get update` on a GitHub runner refreshes six repositories: the
Ubuntu archive plus Microsoft, azure-cli, Google and Chrome. None of
them carry anything simplepool builds against, so the step made every
build depend on all six being reachable in order to fetch 570 kB of
headers. The runner image already ships current lists for the Ubuntu
archive — a plain update reports `Hit:` on the base suite — so the
index on disk is enough to install from.

All four apt steps now call .github/scripts/apt-install.sh, which
installs with no index refresh, bounds every fetch
(Acquire::http::Timeout=20, Retries=3), and falls back to a single
`timeout 180 apt-get update` only if the install actually fails — the
one case the shipped index cannot serve is a package superseded by a
security update whose .deb has left the pool. Every step gets
timeout-minutes: 5, and build-test gets a job-level limit it never had,
which is why nothing capped the 29 minutes.

README: the top described a "solo-mining stratum server" and the body
still said "There is no PPS, no inter-miner reward sharing" — both
written before pps-classic existed and both now false. Those claims are
scoped to `solo`, with the pps-classic inversion stated next to them.
Also drops the stale "sibling project ... in this same monorepo"
framing, fixes a link to ../docs/TESTING.md that pointed outside the
repo, removes include/ from the layout (it doesn't exist) and adds the
modules that do, marks the three shipped roadmap items as shipped, and
states the daily payout cadence where miners will look for it. Points
the source link at LayerTwo-Labs, which is where releases and CI
actually live; the author attribution is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rsantacroce
rsantacroce merged commit bddd0b4 into main Aug 18, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant