satoshi 2f4ed4aa88 Fix BTC-vs-source-IP confusion; redesign user page; OSS + TLS icons
ckpool's stratum_instance.address (exposed as the "address" field in
the runtime JSON) is the SOURCE IP of the connection — set from
inet_ntop in connector.c — not the BTC payout address. The miner's
BTC payout comes from the stratum username, which ckpool stores in
worker.user (and in the dotted prefix of worker.workername).

Every "user" reference in the dashboard was reading c.address and
treating it as the BTC. Effects:

  • clicking an online miner navigated to #/user/<source-ip>; the
    UserDetailPage filters never matched and the page rendered with
    junk values (or the user struct's stale residual hashrate when
    the BTC happened to come from a sibling row).
  • offline-miner clicks worked, but totals came from user.dsps*
    which decay slowly inside ckpool, so a miner that had just
    disconnected still showed positive hashrate for several minutes.
  • the "Best (ever)" tile fell back to bestdiff (session) when
    bestever was zero, so it lied about its semantics.

Fixes:

  • Add btcAddressOf() helper and use w.user (or it) when extracting
    the BTC for the user-link button. The source IP gets its own
    sub-line under the worker name, clearly labelled.
  • Redesign UserDetailPage: filter clients by workername prefix
    against the BTC, never by c.address; compute hashrate totals by
    SUMMING the user's currently-connected clients (so 0 online
    clients => 0 hashrate, no stale decay artifacts); compute
    best_ever as max across the user's worker.bestever values; show
    online/total worker counts and a per-worker status pill.
  • Add an explorer link (mempool.space) for the user's BTC.

TLS detection moves to a clean signal: ckpool now binds two stratum
sockets — public plaintext and loopback-only. stunnel forwards to
the loopback bind, so TLS clients arrive with c.server == 1. The
dashboard reads that and renders a green TLS pill next to the
worker name. No source-IP heuristics needed.

Open-source mark: new isOpenSource() heuristic over the stratum
useragent matches Bitaxe family (NerdAxe / NerdQAxe / NerdMiner /
NerdOctaxe / Lucky / QAxe / MCCM), Braiins OS, cgminer / bfgminer /
ckminer, and ESP32 builds. Renders as an orange ★ next to the
hardware label, matching public-pool's convention.

types.ts: document StratumClient.address (source IP, not BTC) and
add the previously-undeclared `server` field. Surfacing the runtime
value that has been there all along since cfb0f83.
2026-04-26 18:41:05 +03:00
2026-04-12 19:41:13 +03:00

Kamado Pool

A modern, feature-complete solo Bitcoin mining pool built on a patched fork of CKPool, with a real-time web dashboard and a Go-based API middleware that surfaces everything CKPool knows.

Why Kamado?

Existing CKPool-based solutions (like Bassin for Umbrel) read only a handful of periodic stats files and miss most of CKPool's rich data. Kamado talks directly to CKPool's Unix socket API to expose:

  • Real-time per-client data: hashrate, difficulty, user agent, hardware detection
  • Full block-found history with height, hash, reward, and solving worker
  • Per-worker and per-client best share tracking (current + all-time)
  • Network difficulty, pool efficiency, expected time to block
  • Live dashboard updates via WebSocket (no 60-second file polls)

Architecture

┌────────────────────────────────────────────────────┐
│  ckpool-solo (C)  ──Unix socket──►  kamado-api (Go) │
│   ports: 3333                             ports: 80 │
│                                                    │
│   ▲ stratum                         ▲ HTTP/WS     │
│   │                                 │              │
│  Miners                           Browser          │
│                                                    │
│  bitcoind ◄──── RPC + ZMQ ────── ckpool + kamado-api│
└────────────────────────────────────────────────────┘

Three main components:

Component Language Purpose
ckpool/ C Stratum server, share validation, block submission
api/ Go Socket client, REST/WebSocket API, persistence
ui/ Svelte Real-time dashboard

Phases

  • Phase 1 — Fork & fix CKPool, build infrastructure
  • [~] Phase 2 — Go API middleware
    • Phase 2a: CKPool socket client, bitcoind RPC, state aggregator, REST API
    • Phase 2b: CKPool log tailer, block history, stdlib WebSocket push
    • Phase 2b.5: ZMQ block notifier, SQLite persistence (deferred until s9pk repo exists — need real Go build env for new deps)
  • ckpool patch 0001: expose bestever in runtime socket JSON so the UI can show "this round" and "all-time" best share side by side
  • [~] Phase 3 — Svelte UI dashboard (skeleton: header, pool overview, miners table, blocks, best shares leaderboard; live WS updates)
  • Phase 4 — Monorepo Docker build: kamado-api embeds ui/dist via //go:embed and serves it at /. The api Dockerfile has a node stage that builds the UI before the Go stage embeds and builds the binary; docker-compose uses the repo root as build context so both api/ and ui/ are visible.
  • Phase 5 — Testing (regtest, testnet4), polish

Quick start (dev)

cp .env.example .env          # set POOL_BTCADDRESS and bitcoind creds
make up                       # build + start ckpool + api
curl localhost:8080/api/health
curl localhost:8080/api/pool

REST endpoints:

Route Returns
GET /api/health CKPool + bitcoind health
GET /api/pool Pool stats + derived hashrate windows + chain info
GET /api/users All users from users socket command
GET /api/workers All workers from workers socket command
GET /api/clients All connected stratum sessions (useragent, IP, diff)
GET /api/blocks Recent solved blocks (in-memory ring, SQLite in Phase 2b.5)
GET /api/snapshot Full merged snapshot (everything)
GET /api/ws WebSocket push: full snapshot on every refresh + on solve

StartOS packaging lives in a separate repository.

Upstream

CKPool by Con Kolivas: https://bitbucket.org/ckolivas/ckpool

Pinned commit: see ckpool/CKPOOL_COMMIT

License

GPL-3.0. CKPool itself is distributed under GPL-3.

S
Description
No description provided
Readme
640 KiB
Languages
Go 46.7%
Svelte 36.4%
Shell 9.2%
TypeScript 4.7%
Dockerfile 1.4%
Other 1.5%