OpenCSV

RWAs, stables, and more — verified by the parties to a payment, not by a consensus network. Shielded transfers, auditable supply, anchored to Bitcoin with a 64-byte footprint. No fork.

Watch it end to end

Eighty seconds: mint, anchor, off-chain transport, scan-first verification, batching — and what you trust.

Rendered with Remotion from web/animation.

How it works

Bitcoin provides ordering and availability. Everything else — amounts, coins, validity proofs — moves directly between sender and recipient, and the recipient verifies it client-side.

01 — Mint

Issuer creates supply

The issuer signs a mint and anchors it on Bitcoin: MINT ∥ asset_id ∥ V — amount and asset public, so anyone can audit supply. New coins go out as hiding commitments; owners stay private.

02 — Send

Pay like sending a message

A transfer anchors only the spent coins' nullifiers (64 opaque bytes). The coins themselves — plus a recursive proof of their entire ancestry — travel off-chain to the recipient, e.g. over Signal.

03 — Verify

Recipient checks, chain sleeps

The recipient verifies one constant-size proof (valid issuance → conservation-respecting history) and one Bitcoin anchor (first occurrence of the nullifier, k confirmations). Accept or reject — done.

See it working

The real CLI against a real bitcoind (regtest): every anchor is a broadcast Bitcoin transaction carrying a 64-byte OP_RETURN record — no demo chain, no mocks.

captured 2026-08-01 11:34 UTC · regtest · opencsv-rs@aaadae9

Issuer initializes a USD asset and mints 100 to Bob; the anchor transaction is broadcast and confirmed on regtest
The issuer creates a USD asset and mints 100 to Bob — the anchor is a real transaction, confirmed on-chain (gettransaction shows 6 confirmations).
Bob verifies the mint consignment: VERIFIED 100, coins stored, balance 100
Bob verifies the consignment — constant-size proof plus the on-chain anchor — and his wallet credits the coins.
Bob sends 60+40 back to the issuer (VERIFIED); a double-spend of the same coins is REJECTED by the first-occurrence rule; the supply audit reads 100 from chain data
Bob sends 60+40 back (VERIFIED); re-anchoring the same nullifiers loses to first occurrence (REJECTED); the public supply audit sums mints − redeems from chain data.

Properties

OpenCSV extends Shielded CSV's client-side validation with the predicates an RWA actually needs.

Comparison

Where OpenCSV sits among RWA and client-side-validation designs.

Client-side validationShielded transfersAuditable supplyIssuer-gated issuanceTrustless light verificationFork-free on Bitcoin
ERC-20 (Ethereum)nonoyesyestrusted RPCn/a
RGByespartialper-contractyesfull history rescanyes
Taproot Assetsyespartialissuer proofsyesissuer proofsyes
Zcashno (own chain)yesnonolightwalletd (trusted)no
Shielded CSVyesyesnonofull scan or trusted indexeryes
OpenCSVyesyesyesyescompact filters + PoW, on-deviceyes

The last two columns are where OpenCSV earns its keep. Issuer-gated issuance and auditable supply make it an RWA scheme rather than a bearer asset. The deeper one is light verification: in plain Shielded CSV, checking a double-spend means scanning every nullifier the chain has ever carried (or trusting someone who did) — fine on a desktop, impossible on a phone. OpenCSV's marker output makes anchor blocks discoverable through the same compact block filters light wallets already sync, so a phone proves "this coin was never spent before" with proof-of-work and a few kilobytes per block — no trusted server, no full scan. That's the difference between client-side validation as a theory and client-side validation that runs in your pocket.

Roadmap

From paper to a payment that arrives like a text message.

  1. Paper & site — done

    Scheme specification, security analysis, comparison. You are here.

  2. Rust core — real PCD, working

    opencsv-core + opencsv-pcd: Poseidon2 commitments and nullifiers over BabyBear, mint/transfer/redeem predicates as hand-written AIR, in-circuit FRI recursion. Transfers verify two predecessor proofs in-circuit: 56 KB proofs, 3.6 ms verification, constant in history length (~3 s proving, release, 64-core Xeon). The full flow — mint → shielded transfer → double-spend rejected → redeem → public supply audit — passes end to end.

  3. Formal verification — done

    Lean 4 mechanization of the protocol logic: inflation soundness, conservation, nullifier uniqueness, receiver correctness. Sorry-free; all cryptographic hardness isolated in labeled axioms.

  4. Signal client — working, live-tested

    Consignments delivered as E2E-encrypted Signal messages; a payment arrived on a physical iPhone and rendered +100 USD · verified; the phone proved a transfer on-device (~1 s) and the CLI verified it. Both directions over production Signal, audits agreeing.

  5. Scan-first indexing — working

    A protocol-constant marker output makes anchor blocks discoverable via compact filters. A real consignment was verified with no RPC and no indexer — 320 filter bytes + 1,140 block bytes for the window — and an anchor hand-crafted with raw bitcoin-cli from the spec was discovered by the scan engine purely via the filter walk. Two implementations, one protocol, zero coordination.

  6. Field validation — next

    On-device sync bandwidth, battery, and receive latency on real phones on signet; mainnet beta after that.