Phase 1: CKPool build infrastructure

Forks CKPool-solo at upstream commit cfb0f83b (v1.0) via a multi-stage
Docker build, with an env-driven entrypoint that renders ckpool.conf from
a template. The pinned commit already includes every fix referenced in
Bassin issue #29 (workbase_id double increment, extended low-power
timeouts, configurable dropidle, vardiff burst handling).

No patches are applied yet — the patches/ directory holds the workflow
and build wiring so Kamado-specific patches can be added incrementally.

Build is portable across aarch64/x86_64: yasm is intentionally omitted
so CKPool falls back to its C SHA256, and CFLAGS override drops upstream's
default -march=native. Runtime image ships ckpool and ckpmsg for socket
debugging; share logging (-L) is enabled by default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
satoshi
2026-04-12 19:41:13 +03:00
co-authored by Claude Opus 4.6
commit d48035b366
12 changed files with 469 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
cfb0f83b70d7b382b85d2bd0710cf4cb2dda4007
+1
View File
@@ -0,0 +1 @@
https://bitbucket.org/ckolivas/ckpool.git
+82
View File
@@ -0,0 +1,82 @@
# ============================================================================
# CKPool-solo build stage
# ============================================================================
# Builds a patched ckpool binary from upstream source at a pinned commit.
# Binaries land in /build/ckpool/src/ — we copy `ckpool` and `ckpmsg` into
# the runtime image. We do NOT `make install` because upstream's
# install-exec-hook calls setcap which fails inside a docker build.
#
# Portability:
# - No yasm installed -> ckpool falls back to its portable C SHA256
# implementation. This trades some per-core hashrate validation
# throughput for a binary that runs on any x86_64/aarch64 CPU
# regardless of the build machine's feature flags.
# - We override CFLAGS to drop the upstream default `-march=native`
# for the same reason.
# ----------------------------------------------------------------------------
FROM debian:bookworm-slim AS ckpool-build
ARG CKPOOL_REPO=https://bitbucket.org/ckolivas/ckpool.git
ARG CKPOOL_COMMIT=cfb0f83b70d7b382b85d2bd0710cf4cb2dda4007
RUN apt-get update && apt-get install --no-install-recommends -y \
build-essential \
autoconf \
automake \
libtool \
pkg-config \
libzmq3-dev \
ca-certificates \
git \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
RUN git clone "${CKPOOL_REPO}" ckpool \
&& cd ckpool \
&& git checkout "${CKPOOL_COMMIT}"
# Apply Kamado patches in alphabetical order, if any exist
COPY patches/ /tmp/kamado-patches/
RUN set -eux; \
cd /build/ckpool; \
for p in /tmp/kamado-patches/*.patch; do \
[ -f "$p" ] || continue; \
echo "Applying $(basename "$p")"; \
git apply --verbose "$p"; \
done
# Configure and build. Explicit CFLAGS override upstream's default
# `-O2 -Wall -march=native`. We keep -O2 -Wall but drop -march=native.
RUN cd /build/ckpool \
&& ./autogen.sh \
&& CFLAGS="-O2 -Wall -pipe" ./configure --prefix=/usr/local \
&& make -j"$(nproc)"
# Sanity check
RUN test -x /build/ckpool/src/ckpool \
&& test -x /build/ckpool/src/ckpmsg \
&& file /build/ckpool/src/ckpool || true
# ============================================================================
# Runtime stage (minimal)
# ============================================================================
FROM debian:bookworm-slim AS ckpool-runtime
RUN apt-get update && apt-get install --no-install-recommends -y \
libzmq5 \
ca-certificates \
tini \
&& rm -rf /var/lib/apt/lists/*
COPY --from=ckpool-build /build/ckpool/src/ckpool /usr/local/bin/ckpool
COPY --from=ckpool-build /build/ckpool/src/ckpmsg /usr/local/bin/ckpmsg
COPY config/ckpool.conf.template /etc/ckpool/ckpool.conf.template
COPY entrypoint.sh /usr/local/bin/ckpool-entrypoint.sh
RUN chmod +x /usr/local/bin/ckpool-entrypoint.sh
RUN mkdir -p /run/ckpool /var/lib/ckpool /var/log/ckpool
EXPOSE 3333
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/ckpool-entrypoint.sh"]
+23
View File
@@ -0,0 +1,23 @@
{
"btcd": [
{
"url": "${BITCOIN_RPC_HOST}:${BITCOIN_RPC_PORT}",
"auth": "${BITCOIN_RPC_USER}",
"pass": "${BITCOIN_RPC_PASSWORD}",
"notify": ${BITCOIN_NOTIFY}
}
],
"btcaddress": "${POOL_BTCADDRESS}",
"btcsig": "${POOL_BTCSIG}",
"blockpoll": ${BLOCKPOLL_MS},
"update_interval": ${UPDATE_INTERVAL_S},
"serverurl": [
"0.0.0.0:${STRATUM_PORT}"
],
"mindiff": ${MINDIFF},
"startdiff": ${STARTDIFF},
"maxdiff": ${MAXDIFF},
"dropidle": ${DROPIDLE},
"zmqblock": "${ZMQ_BLOCK}",
"logdir": "${LOGDIR}"
}
+96
View File
@@ -0,0 +1,96 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# ckpool-solo entrypoint for Kamado Pool
#
# Reads configuration from environment variables, renders the ckpool.conf
# from the template, and execs ckpool-solo.
#
# Required env:
# POOL_BTCADDRESS - Bitcoin address that receives block rewards
# BITCOIN_RPC_HOST - e.g. bitcoind, 127.0.0.1
# BITCOIN_RPC_PORT - e.g. 8332 (mainnet) / 48332 (testnet4)
# BITCOIN_RPC_USER - RPC username
# BITCOIN_RPC_PASSWORD - RPC password
#
# Optional env (with defaults):
# STRATUM_PORT=3333
# POOL_BTCSIG="/Kamado Pool/"
# BLOCKPOLL_MS=100
# UPDATE_INTERVAL_S=30
# MINDIFF=1
# STARTDIFF=42
# MAXDIFF=0 (0 = unlimited)
# DROPIDLE=0 (seconds; 0 = never drop idle clients)
# BITCOIN_NOTIFY=true (use bitcoind blocknotify/walletnotify)
# ZMQ_BLOCK="" (e.g. tcp://bitcoind:28332)
# LOGDIR=/var/log/ckpool
# SOCKET_DIR=/run/ckpool
# SHARE_LOG=1 (1 = enable -L share logging)
# ----------------------------------------------------------------------------
set -eu
: "${POOL_BTCADDRESS:?POOL_BTCADDRESS is required}"
: "${BITCOIN_RPC_HOST:?BITCOIN_RPC_HOST is required}"
: "${BITCOIN_RPC_PORT:?BITCOIN_RPC_PORT is required}"
: "${BITCOIN_RPC_USER:?BITCOIN_RPC_USER is required}"
: "${BITCOIN_RPC_PASSWORD:?BITCOIN_RPC_PASSWORD is required}"
STRATUM_PORT="${STRATUM_PORT:-3333}"
POOL_BTCSIG="${POOL_BTCSIG:-/Kamado Pool/}"
BLOCKPOLL_MS="${BLOCKPOLL_MS:-100}"
UPDATE_INTERVAL_S="${UPDATE_INTERVAL_S:-30}"
MINDIFF="${MINDIFF:-1}"
STARTDIFF="${STARTDIFF:-42}"
MAXDIFF="${MAXDIFF:-0}"
DROPIDLE="${DROPIDLE:-0}"
BITCOIN_NOTIFY="${BITCOIN_NOTIFY:-true}"
ZMQ_BLOCK="${ZMQ_BLOCK:-}"
LOGDIR="${LOGDIR:-/var/log/ckpool}"
SOCKET_DIR="${SOCKET_DIR:-/run/ckpool}"
SHARE_LOG="${SHARE_LOG:-1}"
mkdir -p "$LOGDIR" "$SOCKET_DIR"
TEMPLATE=/etc/ckpool/ckpool.conf.template
CONF=/etc/ckpool/ckpool.conf
# Simple placeholder substitution (no envsubst dependency).
# We intentionally don't use eval/printf tricks — sed is safe and predictable.
sed \
-e "s|\${BITCOIN_RPC_HOST}|${BITCOIN_RPC_HOST}|g" \
-e "s|\${BITCOIN_RPC_PORT}|${BITCOIN_RPC_PORT}|g" \
-e "s|\${BITCOIN_RPC_USER}|${BITCOIN_RPC_USER}|g" \
-e "s|\${BITCOIN_RPC_PASSWORD}|${BITCOIN_RPC_PASSWORD}|g" \
-e "s|\${BITCOIN_NOTIFY}|${BITCOIN_NOTIFY}|g" \
-e "s|\${POOL_BTCADDRESS}|${POOL_BTCADDRESS}|g" \
-e "s|\${POOL_BTCSIG}|${POOL_BTCSIG}|g" \
-e "s|\${BLOCKPOLL_MS}|${BLOCKPOLL_MS}|g" \
-e "s|\${UPDATE_INTERVAL_S}|${UPDATE_INTERVAL_S}|g" \
-e "s|\${STRATUM_PORT}|${STRATUM_PORT}|g" \
-e "s|\${MINDIFF}|${MINDIFF}|g" \
-e "s|\${STARTDIFF}|${STARTDIFF}|g" \
-e "s|\${MAXDIFF}|${MAXDIFF}|g" \
-e "s|\${DROPIDLE}|${DROPIDLE}|g" \
-e "s|\${LOGDIR}|${LOGDIR}|g" \
-e "s|\${ZMQ_BLOCK}|${ZMQ_BLOCK}|g" \
"$TEMPLATE" > "$CONF"
# If ZMQ is not configured, strip the zmqblock line entirely.
# The template keeps zmqblock as a non-final key with a trailing comma,
# so removing the whole line leaves valid JSON.
if [ -z "$ZMQ_BLOCK" ]; then
sed -i '/"zmqblock":/d' "$CONF"
fi
echo "[kamado] rendered ckpool.conf:"
sed "s|\"pass\": \".*\"|\"pass\": \"<redacted>\"|" "$CONF"
echo
# Build command line
CMD="/usr/local/bin/ckpool --btcsolo --config $CONF --sockdir $SOCKET_DIR"
if [ "$SHARE_LOG" = "1" ]; then
CMD="$CMD --log-shares"
fi
echo "[kamado] exec: $CMD"
exec $CMD
+58
View File
@@ -0,0 +1,58 @@
# CKPool Patches
Patches applied on top of the upstream CKPool commit pinned in `../CKPOOL_COMMIT`.
Patches are applied in alphabetical order by filename. Use a numeric prefix to enforce ordering:
- `0001-short-description.patch`
- `0002-another-fix.patch`
## Current state
**No patches are applied.** The pinned upstream commit (`cfb0f83b`, tagged
as version 1.0) already includes every fix that Bassin issue #29 asked to
backport, plus several improvements:
| Upstream commit | What it fixes |
| --------------- | -------------------------------------------------------------- |
| `a439cf96` | workbase_id double increment bug |
| `590fb2a2` | Extended timeouts for low-powered miners (NerdMiner, ESP32) |
| `b13f3eee` | Configurable `dropidle` timeout (exposed via our env var) |
| `66db3aa3` | Better vardiff for bursty hashers |
| `130c755d` | Fix unlikely fopen segfault |
| `0bd3d751` | Consistent error field in mining.submit rejections |
| `988b2687` | Version 1.0 — longstanding stability bump |
Kamado therefore starts from a CKPool that is strictly ahead of what Bassin
ships today.
## When to add a patch
Use this directory for:
1. Fixes needed before they land upstream (and only after attempting
to submit upstream first).
2. Kamado-specific behavior changes that would not be accepted upstream —
e.g. tighter integration hooks with `kamado-api`.
3. Temporary workarounds with a clear removal plan, documented in the
patch commit message.
Do NOT use this directory for:
- Pure configuration changes (expose via the entrypoint env vars instead).
- Build system tweaks (put those in the Dockerfile).
## Creating a patch
From a clean clone of upstream at the pinned commit:
```sh
git clone https://bitbucket.org/ckolivas/ckpool.git
cd ckpool
git checkout $(cat /path/to/KamadoPool/ckpool/CKPOOL_COMMIT)
# ... make your changes ...
git diff > /path/to/KamadoPool/ckpool/patches/0001-my-fix.patch
```
The Dockerfile applies each `*.patch` file in this directory with
`git apply --verbose` during the build.