Private Bitcoin payments via Shielded CSV — no new chain, no token, no consensus change, no trusted operator. Only Bitcoin, zero-knowledge proofs, and the user's own keys.
The public API layer for zkCoins — REST on top of the node's internal kernel RPC. This is the multi-tenant, hosted-wallet service surface that wallets, the SDK, and the explorer speak. It is optional and operator-run; the trustless core is the node.
Full system docs: docs.zkcoins.com · Specification: docs.zkcoins.com/specification
zkCoins lets you send value on Bitcoin without anyone seeing the amount, the asset, who paid, or who received. Bitcoin stores only opaque markers that a spend happened — not the coin's contents, which travel privately between sender and receiver as a small encrypted bundle. Double-spend protection is the chain's job; your seed derives every key, your wallet is the only thing that can spend, any node can serve you, and you verify everything against Bitcoin yourself. Built on the zkCoins concept (Robin Linus) and the Shielded CSV construction (Jonas Nick, Liam Eagen, Robin Linus).
| Layer | What it is | Repo |
|---|---|---|
| App · Explorer | end-user wallet (LNURL receive) · public explorer web-app | zk-coins/app · zk-coins/explorer |
| SDK | thin TypeScript client — on-device keys, signing, node/API calls | zk-coins/sdk |
| zkCoins API | public REST, hosted-wallet service (optional) | zk-coins/api ← this repo |
| zkCoins node | trustless kernel — scan · accumulator · verify · prove · store · publisher | zk-coins/node |
| bitcoind · Nostr relay | Bitcoin L1 settlement and ordering · off-chain transport and data availability | upstream (own or external) |
Supporting repos: zk-coins/research, zk-coins/plonky2, zk-coins/docs.
The API layer sits outward of the node. It consumes the node's internal kernel RPC (gRPC kernel.v1, specification §7.8) and exposes the public REST API (§7.5) to wallets, the SDK, the app, and the explorer — REST outward, gRPC inward.
- A planned / not yet implemented API-local non-value-bearing database (LNURL mappings,
username/aliasing, rate-limits, push-subscription registrations) is in scope for this layer. The value-bearing data — coins, proofs, bundles, the nullifier accumulator — stays in the node (§4.8); the API layer never touches the node's database directly. - It never touches Bitcoin and holds no SPEND key. Capability-gating lives here; rate-limiting is Kernel ErrorInfo translation (
rate_limited), not an API-local limiter. Proving, broadcasting, and chain scanning stay in the node. - Running it is optional: a sovereign personal node serves its own wallet directly; the API layer is the "public service node" role that hosts other accounts.
This repository is the standalone API process: src/startup.rs loads
config, connects the kernel client (connect_lazy / ZKCOINS_KERNEL_ADDR),
and serves REST. The node is the trustless
kernel, not the public API. The full design is specified in
§6.1 (kernel and API),
§7.5 (REST), and
§7.8 (kernel RPC).
- Full §7.5 endpoint inventory (method, capability, feature, kernel RPC):
docs/rest-surface.md. - Rust process (
axum+tonic 0.13.1client):GET /,GET /health, info/chain reads, the job surface, attest/grants (including grant revoke), pull/records/account,GET /v1/receipts/stream(SSE overSubscribeReceipts), bootstrap/publish, token provenance, and optional Blossom. No placeholder routes for unbuilt keys. - OwnershipProof for attest/grants is verified at the API edge (BIP-340, action-bound domain,
chan_bind,request_hash) before any kernel call that would consume a challenge nonce. GET /discovery follows registration viaServedSurface— only served keys are advertised. Known-but-disabled inventory paths answer404 feature_disabled. The 31-key catalogue is the inventory (grants_revoke_challenge,grants_revoke,token_provenanceincluded; noblossom_delete; append-only Blossom).- Kernel contract: carried
proto/kernel/v1/kernel.protowith SHA-256 identity pin (src/proto_identity.rs); REST errors fromErrorInfo.metadata["http_status"]only (API-local auth failures use §7.5401 unauthorizeddirectly). - Codegen lives in the workspace member
kernel-proto(tonic client stubs only). Workspacedefault-members = ["."]keeps defaultcargo clippy/cargo teston the api package so generated code is not linted. - Fail-closed env:
ZKCOINS_BIND_ADDR,ZKCOINS_KERNEL_ADDR,ZKCOINS_FEATURES,ZKCOINS_PUBLIC_HOST(see the inventory doc). Optional Blossom store:ZKCOINS_BLOSSOM_STORE(+ max bytes / allowed ops companions).
MIT