Skip to content

Add per-worker rejects observability to the ckpool lane - #97

Merged
RobertClarke merged 8 commits into
1.x.xfrom
ckpool-rejects-observability
Jul 31, 2026
Merged

Add per-worker rejects observability to the ckpool lane#97
RobertClarke merged 8 commits into
1.x.xfrom
ckpool-rejects-observability

Conversation

@RobertClarke

@RobertClarke RobertClarke commented Jul 26, 2026

Copy link
Copy Markdown
Member

CKPool now aggregates every Stratum submission by worker and reason (accepted, above_target, stale, duplicate, invalid_job, invalid_ntime, invalid_version, malformed) plus block-candidate submitblock outcomes, summing assigned difficulty per bucket, via a purely additive patch on the pinned upstream applied after the existing qbit patches. Tallies are written atomically (tmp+rename) to pool/rejects.status every 60 seconds as cumulative counters for exporters, with the contract documented in ckpool/README.md and cross-linked from docs/README.md; share validation, share responses, and block submission behavior are unchanged. A live regression/load suite drives a real patched binary over Stratum — covering the full reason taxonomy, both block outcomes, atomic-write parses under concurrent load, and exact per-worker count/difficulty conservation — via make test-ckpool-rejects-observability, a new scripts/build-patched-ckpool.sh, and a dedicated CI job. tests/fake_qbit_rpc.py gains additive knobs (scripted submitblock results, decoderawtransaction, a /control endpoint), and fast always-on tests pin the patch wiring, ordering, and tamper-evidence contract.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Note

Medium Risk
Touches hot-path share handling in ckpool's stratifier (locks and hooks on every submit) but is designed as read-only observability with bounded memory; regression coverage is strong, yet production mining behavior still depends on patch correctness under load.

Overview
Adds additive ckpool observability: every mining.submit and local submitblock outcome is tallied by worker and reason, then exported once per 60s stats cycle to pool/rejects.status via tmp+rename. Share validation, Stratum responses, and block submission paths are not changed beyond recording counters after existing classification.

The patched stratifier.c defines stable reason buckets (accepted, above_target, stale, duplicate, invalid_job, invalid_ntime, invalid_version, malformed) plus block_accepted / block_rejected, with per-bucket count and assigned-difficulty diff. Per-worker rows are lazy and capped (default 4096 via QBIT_REJECTS_WORKER_LIMIT); overflow aggregates in worker_overflow when truncated.

Build & deploy wiring: qbit-rejects-observability.patch is applied after the existing qbit ckpool patches in the Docker image; compose.yaml and .env.example forward the worker limit. scripts/build-patched-ckpool.sh and make test-ckpool-rejects-observability build a local binary for tests; CI adds a dedicated job.

Tests & docs: tests/test_ckpool_rejects_observability.py drives real Stratum against a patched binary (full taxonomy, block outcomes, atomic writes under load); tests/test_ckpool_rejects_patch.py pins patch wiring. tests/fake_qbit_rpc.py gains scripted submitblock, minimal decoderawtransaction, and /control. Operator contract is documented in ckpool/README.md with a cross-link from docs/README.md.

Reviewed by Cursor Bugbot for commit 256116b. Bugbot is set up for automated code reviews on this repo. Configure here.

Aggregate every Stratum submission by worker and reason (accepted,
above_target, stale, duplicate, invalid_job, invalid_ntime,
invalid_version, malformed) plus block-candidate submitblock outcomes,
summing assigned difficulty per bucket, and write an atomic 60-second
pool/rejects.status JSON for exporters. Purely additive observability
patch on the pinned upstream ckpool: no changes to share validation,
share responses, or block submission behavior.

Ship live regression and load tests that drive a real patched binary
over Stratum (make test-ckpool-rejects-observability, new CI job),
fast patch-wiring and tamper-evidence tests, fake-RPC extensions for
scripted submitblock results, and the exporter contract docs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b97a5acd91

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docker/ckpool/qbit-rejects-observability.patch Outdated
Comment thread docker/ckpool/qbit-rejects-observability.patch Outdated
Comment thread docker/ckpool/qbit-rejects-observability.patch Outdated
Comment thread docker/ckpool/qbit-rejects-observability.patch
Copy the pool tally and every worker tally under one rejects_lock hold
so a rejects.status document can never show per-bucket worker sums
exceeding pool totals while submissions are in flight (raised by Codex
and Cursor Bugbot on #97). Worker pointers are collected first without
the lock - ckpool never frees worker instances - and workers authorised
mid-snapshot join the next cycle, so worker rows stay a subset of what
the pool tally has seen.

Also guard the block-outcome worker lookup against a NULL user. The
path is unreachable today (get_user is get-or-create, matching
upstream block_solve), but observability code must never be the thing
that crashes the stratifier.

The live suite now asserts snapshot consistency on every observed
document including mid-load reads, and exact worker/pool equality once
traffic settles; the README documents the guarantee. The Bugbot claim
that the write interval follows update_interval is incorrect and left
unchanged: statsupdate's cycle is hardcoded to 32 x 1.875s = 60s, and
the live test measures ~60s write deltas with update_interval=30.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7da2b5fa00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docker/ckpool/qbit-rejects-observability.patch Outdated
Codex flagged that the export walked every worker instance ever
authorised, letting cheap authorization spam on the public Stratum
port grow the status file, the snapshot allocations, and the copy
performed under the submission-shared rejects_lock. Filter the
snapshot to workers with at least one recorded submission or block
outcome: the relaxed pre-filter read is safe because tallies only
grow, and a worker racing its first submission simply joins the next
60s cycle. The live taxonomy test now authorises an idle worker and
asserts it never appears in the export; the README documents the
bound.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e831a5f000

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docker/ckpool/qbit-rejects-observability.patch Outdated
Comment thread docker/ckpool/qbit-rejects-observability.patch Outdated
Comment thread docker/ckpool/qbit-rejects-observability.patch Outdated
Track reject-observability workers in a lazy, lock-protected append-only registry so status snapshots avoid authorization scans and cannot drop active workers during count/fill races. Cover remote block outcomes and exercise real status replacement under concurrent traffic.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e62710a929

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docker/ckpool/qbit-rejects-observability.patch
Cap per-worker reject records at 4096, aggregate excess attributed events in a lock-consistent overflow tally, and expose truncation metadata. Add real-binary overflow coverage using a lowered test limit while preserving complete pool totals.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ddfee07b44

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ckpool/README.md
Expose the bounded registry setting in the ckpool service and example environment so operators can lower the compiled 4096 maximum. Pin the deployment wiring with the rejects observability contract tests.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit dee3796. Configure here.

Comment thread docker/ckpool/qbit-rejects-observability.patch
Remove the completed temporary file when atomic publication fails and pin both write- and rename-failure cleanup paths.
@RobertClarke
RobertClarke merged commit 1cc820d into 1.x.x Jul 31, 2026
11 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.

2 participants