Grant Application - Zebra-Native Non-Custodial Mining Stack (RobotBase)

Applicant: @wygogogo19 (Yang Wang) — RobotBase, independent infrastructure operator
Category: Infrastructure · Requested: $19,500 over 6 months (milestone-based)
GitHub application: Grant Application - Zebra-Native Non-Custodial Mining Stack (RobotBase) · Issue #439 · ZcashCommunityGrants/zcashcommunitygrants · GitHub

What this is

Zcash is retiring zcashd in favour of zebrad, but mining infrastructure has not followed. We have built — and now operate in production — a Zebra-native, non-custodial Stratum V1 pool: block templates come from our own zebrad v6.3.0 node, and the coinbase transaction itself pays 99% to the miner’s t-address and 1% to the pool’s infrastructure address (ZIP-244 mode 2). There is no pool balance, no withdrawal step and no registration — the username is the payout address.

This grant turns that working system into a reusable public good: an integration test harness and CI, an operator runbook validated by an independent operator, a miner-firmware compatibility matrix, and a stable specification for our six-value-pool telemetry API (transparent / sprout / sapling / orchard / ironwood / lockbox).

Already live today

Honest status — please read this part: everything the pool has accepted came from our own testing, not from third-party miners. Two things have connected: a self-hosted CPU probe, labelled “Self-hosted CPU probe (live Equihash proof)” on the portal, and a rented Antminer Z15 (420 kSol/s, MiningRigRentals, EU-Poland) that we paid for and pointed at stratum+tcp://zec.robotbase.cc:3032 for a 3-hour window on 2026-09-22/23. That ASIC session alone submitted 2,226 accepted shares with 0 stale once vardiff converged (difficulty 512 → 256). No natural third-party miner has connected yet and we have not found a Zcash block. We are not presenting those counters as third-party usage, and we ask that success be measured on published engineering artefacts and operator adoption rather than on block luck.

Budget

Item USD
Startup funding $3,900
Milestones (5) $15,600
Total $19,500

Milestones

# Milestone Amount Target
1 Public repository + architecture, CI on every push, reproducible dev environment $3,120 Month 1
2 Test suite, synthetic-miner simulation harness, public review round $3,900 Months 2–3
3 Operator runbook + container recipe, one independent operator running a pool from the repo $3,120 Months 3–4
4 Six-pool telemetry API spec + miner-firmware compatibility matrix (lightwalletd endpoint optional) $3,900 Months 4–5
5 30-day operational report and handover $1,560 Month 6

What we are not claiming

  • No custody, ever: the engine holds no keys and no funds, and cannot move coins.
  • No token, no VC, no sponsorship — RobotBase is self-funded through unrelated infrastructure work.
  • Milestone 1 is partly delivered already (repository, documentation and CI were published before we applied); the grant pays for the work that makes the stack usable by others, not for what already exists.

Questions, criticism and — especially — anyone interested in being the independent operator in milestone 3 are very welcome here or on the GitHub issue.

AFAIK Light wallets have already updated to use zebrad, such as GitHub - zecrocks/zcash-stack · GitHub (@emersonian’s stack), which is hosted at zec.rocks and has a pretty long directory (https://hosh.zec.rocks)

Where are you getting the impression that light wallets haven’t migrated? And migrating miners is, bluntly put, not your job. Legitimate institutional miners will never use software which doesn’t have the official stamp from ZODL.

Thanks for the pushback — you’re right on the light-client side, and I’ll correct our wording.

On light wallets: agreed. Lightwalletd/Zaino deployments kept pace — the zec.rocks stack (by @emersonian) and directories like hosh.zec.rocks list a healthy set of public endpoints, including Zaino ones. Our line “mining and light-wallet infrastructure has not followed” conflated two different things. I’ll rewrite it to say plainly that mining is the gap we’re addressing, and I’ll drop the “few operators run one” claim in the application unless we can state something narrower and true — uptime, rate limits, region, i.e. the things a wallet can actually depend on.

The mining gap is narrower, but structural. Every widely used pool stack — Miningcore, NOMP/z-nomp and their forks — is written against zcashd’s mining RPC and coinbase handling. With zebrad, getblocktemplate hands back a coinbase bound to blockcommitmentshash; you cannot inject an extranonce into it without recomputing the commitment roots. That’s why those stacks can’t just switch nodes. We had to write a ZIP-244 v6 digest + coinbase builder to make a 99/1 on-chain split work at all — and it’s published under MIT (tag v0.1.0) precisely so it can be audited rather than believed. If a maintained, self-hostable, non-custodial pool engine for zebrad already exists, I’d genuinely like the pointer; I’ll link it in the proposal and reassess what’s left to fund.

On “not your job” and the official stamp: agreed — and that isn’t what we’re proposing. We’re not asking anyone to migrate off anything, and we don’t expect institutional miners to run unaudited software. The engine holds no keys and no balance; the coinbase pays the miner’s own t-address and that split is verifiable on-chain. What the grant buys is tests, CI, an operator runbook, one independent operator validating the deployment path from the repo, and a stable telemetry spec. If ZODL ever wants an official artifact, this is a candidate they can audit, absorb, or reject — that is the point of MIT.

We have already reframed milestone 4 in the application: it is now the six-value-pool telemetry spec plus a miner-firmware compatibility matrix, and the lightwalletd endpoint is explicitly optional — published only if it adds something the existing public server set does not. The parts that matter are the pool engine, its tests, and the telemetry spec.

1 Like

“Thanks for the pushback” + em dashes + instantly morphs approach upon criticism

Yeah no I’m too high for this peace out

Mining is literally solved by Zebrad itself…

Zebrad only exposes getblocktemplate and submitblock via JSON-RPC. ASICs talk Stratum, not JSON-RPC, and Zebrad has no built-in Stratum server or worker session management.

That Stratum bridge is the gap this repo covers.

Milestone 2 is complete, ahead of schedule — and it caught two real bugs.

Quick status against the plan, then the parts worth reading.

Milestone Plan Status
M1 — public repo, CI, reproducible dev env Month 1 Done (published before the grant)
M2 — test suite + synthetic-miner harness + public review Months 2–3 Complete
M3 — operator runbook + one independent operator Months 3–4 Starting now — operator welcome
M4 — six-pool telemetry spec + firmware matrix Months 4–5 In progress — spec landed, matrix next

The test suite, and what it is not

The repository now carries 107 offline tests that run with nothing but a CPython interpreter — no dependency install, no node, no solver, no network:

python3 tests/_run.py     # 107 tests, OK in ~1.3 s

What matters is what they run against. The fixtures are not invented: a verbatim getblocktemplate/getblocksubsidy pair from our production zebrad, and two shares the live pool actually accepted, with their 140-byte headers and 1344-byte Equihash(200,9) solutions. So the accept path is exercised with a genuine proof of work, and a change in how the engine handles a real mainnet template fails the suite.

Coverage is concentrated where it counts — the consensus-critical arithmetic:

Module Coverage
build_coinbase.py (the 99/1/Lockbox split) 98.1%
zcash_v6.py (transaction digests) 92.9%
overall 50.8%

CI runs on every push across Python 3.11 / 3.12 / 3.13, with a coverage floor so the number cannot slide silently. tests/synthetic_miner.py is the harness behind the end-to-end tests: a hashrate-free miner that speaks Stratum over a real socket to the real engine and replays a pre-computed, genuinely valid Equihash solution.

The two bugs the suite found

This is the honest part, and the reason we built the suite early. Writing the coinbase tests surfaced two defects in how the block header was assembled. Both were silent: shares stayed self-consistent, so nothing looked wrong until the tests compared our output against the node’s own.

  1. Coinbase txid. We were computing the coinbase transaction id as dsha256(raw). A Zcash v5/v6 txid is a ZIP-244 digest, and a shielded coinbase cannot be re-derived from its raw bytes at all. The job now uses the txid the node itself publishes (coinbasetxn.hash).
  2. Merkle root. We were walking the template’s transaction list as if it were a merkle branch. It is not: with two or more transactions, the coinbase’s sibling is a subtree hash. The root is now built as a tree.

Consequence before the fix: a solved block would have been rejected by the network (bad-txnmrklroot). After the fix, the engine reproduces the node’s own defaultroots.merkleroot byte-for-byte over a live template — that comparison is now a test (tests/test_job_contract.py), not a one-off check. Both fixes are deployed to both production engines.

We are reporting this rather than quietly patching it because “the test suite found real bugs and we fixed them” is the point of the milestone, and because a reviewer can re-run the same comparison on any future template.

Live production numbers

As of 2026-10-01 (block height 3,502,663):

  • 18,100+ shares accepted, 21 rejected (99.88% valid), cumulative across engine restarts.
  • Zebra 6.3.0, zero restarts since 2026-09-14 — the node has been up continuously through the whole test-and-fix cycle, and its chain view is 100% synced at the live tip.
  • The engine holds no keys and no funds; the 99% / 1% split is inside the coinbase, unchanged by any of the above.

Honest caveat, unchanged from the application: the pool has not found a mainnet block, and the shares above are still the pool’s own testing rigs, not third-party miners. We are not presenting them as adoption.

Repository and production are the same code

The published pool.py and the engine running in production (both the front-end and the fallback) are token-identical after normalising comments and string literals — 8,437 identical tokens. This is a claim a reader can verify, not a slogan; the diff is comments and localised strings, never logic.

Milestone 4 is underway

The six-value-pool telemetry spec has landed as formal JSON Schema contracts in schemas/ — one contract per public surface (/api/zec/summary, /api/factors, the node status page, and the MCP zec_chain_info tool), plus a shared definition library and a documented versioning policy. Each contract is checked against a frozen real payload in CI, and you can validate a live fetch yourself with the shipped, dependency-free validator. The miner-firmware compatibility matrix is the next piece.

Want to be the independent operator (M3)?

Milestone 3 needs one independent operator to stand up a pool from the repository alone and tell us where the runbook is wrong. If that is you — or you know a miner who wants to help pressure-test a Zebra-native pool — reply here or open an issue. That is the milestone the grant is really paying for, and it is the one that needs someone other than us.

Milestone 3 progress update — and a call for one independent operator

Quick update on Milestone 3 (operator runbook + container recipe), pushed as 7681b8fc7:

  1. Container recipe. Added a Dockerfile (standard-library only, so the image installs nothing; it runs as unprivileged uid 10001 to match the uid the official zfnd/zebra image drops to) and a self-contained deploy/compose.yaml that runs the node and the engine together, sharing the RPC cookie through a dedicated volume so the engine never sees the chain data.

  2. Operator runbook. Published docs/OPERATOR-RUNBOOK.md: node sizing, the non-custodial payout constraints, both setup paths, and a four-step acceptance test an operator can run before trusting the pool.

  3. Guardrails & hygiene. Writing the runbook surfaced that the engine takes its config path from ZECPOOL_CONFIG and ignores a command-line argument, while both the README quickstart and the shipped example systemd unit taught the argument form — following either would have failed on a fresh install. Documents and the example unit are fixed; the engine source is deliberately unchanged so the published file stays token-identical to our production engine. .gitignore and a CI assertion now also prevent chain state and runtime credentials from ever being committed.

  4. Still true: 115 offline tests, CI green on Python 3.11/3.12/3.13.


Call for one independent operator to test deployment

To formally close Milestone 3, we want to prove that an operator other than ourselves can stand up the pool using only the documentation.

What you need:

  • A spare box / VPS (~400 GB SSD, 8 GB RAM) capable of syncing zebrad.

  • A Zcash t-address (the fee split and recipient are entirely yours to configure).

  • Willingness to follow the runbook and report where things broke or were confusing.

Details and the reporting checklist are in the tracking issue:

:backhand_index_pointing_right: GitHub Tracking Issue: [Call for Operators] Seeking 1 independent operator to verify deployment runbook (Milestone 3) · Issue #1 · wygogogo19/zebra-stratum-pool · GitHub

You can also reply directly in this thread. We will credit the operator in the final milestone acceptance report.

:backhand_index_pointing_right: GitHub Tracking Issue: [Call for Operators] Seeking 1 independent operator to verify deployment runbook (Milestone 3) · Issue #1 · wygogogo19/zebra-stratum-pool · GitHub

A short correction to the Milestone 4 line in my previous update — and one more thing we need

The status table in my last post said “M4 — in progress, spec landed, matrix next.” That was accurate when I wrote it, but the firmware matrix has since landed as well: docs/FIRMWARE-COMPATIBILITY.md is on main, with executable tests covering four mining.submit shapes.

Milestone 4’s acceptance criteria are not only “the spec is published”. They are that an independent operator or miner reproduces a row of the matrix, and that an external consumer — a wallet project, a researcher or a bot — reads the telemetry spec and confirms it works. The 2026-09-22 Z15 row came from our own rented unit, so it does not count as an independent reproduction, and nobody outside the project has consumed the spec yet.

Both of those, together with the Milestone 3 operator call, are described in the pinned tracking issue:

:backhand_index_pointing_right: [Call for Operators] Seeking 1 independent operator to verify deployment runbook (Milestone 3) · Issue #1 · wygogogo19/zebra-stratum-pool · GitHub

This is a SOLO mining pool. All the reward goes to the miner who found the block - 1% commission. With this payment scheme, you might as well mine by yourself directly with zebra mining API. A pool is meant to share the reward between the miners who searched based on how much work they did.

You’re right, and I’d rather concede the point cleanly than argue semantics.

The live service is solo mining with a bridge attached: 99% of the reward goes to whoever found the block, 1% to the pool. There is no variance sharing — ten miners contributing 10% each does not give each of them ~10% of a block; it gives the finder 99%. The repository’s own first line says “non-custodial solo mining”; calling the engine a “pool engine” in the application is what invited your objection, and that is on me.

On “you might as well mine with the zebra mining API”: that is precisely the gap. zebrad speaks JSON-RPC getblocktemplate / submitblock. The hardware miners that exist for Zcash — Antminer Z15 / Z15 Pro, Innosilicon, the GPU miners — speak Stratum V1. There is no maintained open-source bridge between the two, which is why pointing a Z15 at a Zebra node is not something an operator can do today. Our milestone-4 matrix has one hardware row actually exercised end-to-end: a rented Z15, 2,226 accepted shares, 0 stale, 99.86% of nameplate. A miner whose client already speaks GBT does not need us — and should just run it.

So the honest description of the deliverable is “self-hostable, non-custodial solo-mining bridge for ASIC firmware”, plus the telemetry spec. None of the five milestones promises proportional payouts.

Your comment does raise the design question the grant should answer rather than dodge: can the non-custodial property survive a real pooled payout? I believe it can, and the shape is:

  • The engine already assembles the coinbase output-by-output (lockbox commitments, the miner output, the 1% output). Splitting the 99% across N miner addresses by share weight changes that output list, not the architecture. A transparent output is ~34 bytes; a 2 MB block holds thousands.
  • Miners already identify themselves with a t-address in the worker name (<address>.<rig>), so being paid needs no registration.
  • New work: a PPLNS-style share ledger with a window, an operator-side dust threshold with carry-over into the next block, and a rule for when the reward is smaller than the payee count. Shielded (UA) outputs are ~KB each, so a wide fan-out would be transparent-address based.
  • What stays: no balance, no withdrawal, no accounts. The payout table is materialised in the block itself.

If that is the direction ZCG wants, I’m glad to scope it as an explicit milestone, with the weighting spec published and tested before it touches mainnet. If the view is that Zcash does not need a solo bridge at all, that is also worth saying now — it would change phase 2 more than any code review would.

Yes there are.

"Thank you @hanh and the ZCG committee for the sharp review and pointers. Following the community feedback and having re-evaluated active prior art like sovright/mining-infra, we recognize that the ecosystem need for our proposed stack is narrower than originally anticipated.

Rather than consuming committee bandwidth on an amended scope, we have decided to withdraw this grant application. We will keep our Zebra Stratum bridge open-source for anyone who may find it useful.

We appreciate the committee’s time and wish the Zcash ecosystem continued success!"