Skip to content

Decentralization roadmap: network-layer gaps between today's node and the Shielded CSV peer-to-peer model #170

Description

@TaprootFreak

Scope

This issue scopes the network-topology gap between the current node and the Shielded CSV peer-to-peer model described in eprint 2025/068 and the original zkCoins gist.

It is orthogonal to SPEC.md §15 (D1–D11), which catalogues circuit/protocol divergences. The items below are about how the network is wired: who talks to whom, who holds what state, who can step in if one party disappears. Even with every D-item resolved, the architectural gaps below would remain.

This is a problem inventory only — no solutions are proposed here. Each item is a tracking placeholder for future design discussion.

What Bitcoin actually coordinates today

Exactly one subsystem is reconstructible from the chain alone, by anyone, without trust:

  • The nullifier accumulator (SMT + MMR over the 64-byte commitments published as Taproot inscriptions with the 4242 marker prefix).

That is the entire on-chain coordination surface. It is sufficient for double-spend prevention and nothing else.

What Bitcoin does not coordinate (the gaps)

Every other piece of state lives in the node's Postgres and has no on-chain anchor or off-chain gossip path. Concretely:

State Where it lives Reconstructible from chain?
Per-account balance accounts table (BYTEA bincode) No
Coin proofs Server filesystem, addressed by proof_id No
Username → address mapping usernames table No
num_sends (BIP-32 key-rotation counter) Per-account column No
Mint authority Single PUBLISHER_KEY / MINTING_ADDRESS env vars No
Pending inscription state pending_inscriptions table No

Problem inventory

P1 — Coin + proof transport is implicit and server-mediated

The paper specifies that (coin, coin_proof) is delivered directly from sender to receiver, off-chain. Today, this delivery is implicit: the sender POSTs to /api/send, the server stores the proof under a proof_id, and the same server later credits the recipient's account. There is no peer-to-peer transport — no gossip layer, no mailbox, no relay — and no out-of-band channel a sender could fall back to. If the node is unavailable, the payment cannot move, even if both parties have full Bitcoin chain access.

P2 — Receiver does not perform client-side validation

The defining property of CSV ("the receiver validates the coin proof; the chain does not") is not implemented end-to-end. The server validates the inputs to /api/send, generates the proof, updates its state, and the thin client trusts the resulting balance / num_sends response. No PCD verification runs on the receiver's device. The client has no independent way to detect a malicious or buggy server.

P3 — Proof generation is bound to a single operator's hardware

The Plonky2 prover runs server-side (3–15 min per /api/send on M3 Ultra). A user's ability to transact depends on:

  1. that the server is online,
  2. that the server accepts their request (no censorship),
  3. that the server has not lost or rolled back the prerequisite account state.

There is no path for a user to switch provers, run their own prover, or use a different operator for the same account.

P4 — Account state is non-portable across nodes

accounts, the SMT subtree for an address, the MMR snapshot used for the user's last send, and the cached coin proofs that back the user's balance all live in one server's Postgres. A second independent node, syncing from the same Bitcoin chain, would reconstruct an identical nullifier accumulator but a disjoint account universe. There is no protocol-level export, handoff, or reconciliation path. Two nodes would be two islands sharing only the double-spend register.

P5 — Username registry is server-local and non-portable

/api/username/claim and /api/username/resolve/:username operate against the usernames Postgres table. There is no on-chain commitment, no DNS/Nostr/LNURL anchor, and no cross-node namespace coordination. A username claimed on node A does not exist on node B, and there is no way to migrate or prove ownership of a name when changing operators.

P6 — Mint authority is a single off-chain key

MINTING_ADDRESS and the publisher's signing key are held by the operator. There is no bridge from native BTC (BitVM, one-way peg, federation, or otherwise), so all supply on the running networks is privileged-issued. This is acceptable for the closed testnet, but it means the system has no trust-minimised entry point for value today.

P7 — Publisher monoculture in practice

Code-wise the publisher role is permissionless: any operator running this binary can post nullifiers to Bitcoin. In practice, exactly one publisher exists (api.zkcoins.app). There is no nullifier-gossip layer between potential publishers, no fee market, no fallback if the single publisher stalls, and no protocol mechanism for a user to switch publishers mid-flight.

P8 — Reorg state ownership

The Conditional NAV mechanism described in the paper (and tracked separately as SPEC §15 D7) protects against orphaned-nullifier scenarios. Even with D7 closed inside the circuit, the state ownership question remains a network problem: today the server holds the canonical reorg-resolved view, and clients have no independent way to detect when the server's reorg handling has gone wrong.

P9 — Operator plaintext visibility (network-layer consequence)

Because P3 (server-side prover) and P2 (no client-side verify) hold, every /api/send request reaches the server as plaintext: sender address, recipient address, amount, signature. The request_log and event_log tables capture this in Postgres. Even with the cryptographic privacy goals (D2/D10) closed at the on-chain layer, the operator's visibility into off-chain traffic is a structural consequence of the current topology, not of the circuit.

P10 — Read endpoints expose state without authentication

/api/balance?address= and /api/username/resolve/:username are unauthenticated. The 256-bit address is simultaneously the receive address and the viewing capability for balance + num_sends. Combined with the public username-resolve path, username → address → balance + activity counter is a two-call public lookup. This is a network-layer privacy question (who can ask what) distinct from the on-chain privacy items in §15.

Out of scope for this issue

  • Specific designs, implementations, or migration paths for any of P1–P10.
  • The cryptographic divergences already tracked in SPEC.md §15 (D1–D11).
  • Anything inside the circuit (program-plonky2) or the prover host (script-plonky2).

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions