Update zk-proofs for Protocol 25: BN254 and Poseidon are live - #72
Conversation
CAP-0074 and CAP-0075 both read Status: Final, Protocol version: 25 in stellar-protocol, and mainnet is on protocol 27 — the skill was still calling them proposed and steering builders to attestation workarounds for capabilities that ship natively. - Status table: both CAPs marked Available (Protocol 25+), with the BN254 host-function surface named (crypto::bn254) - Toolchain table: all four rows now on-chain verifiable; UltraHonk routes through Nethermind's rs-soroban-ultrahonk verifier (the stack under OpenZeppelin's Confidential Tokens preview), with a maturity caveat - Noir walkthrough: on-chain verification is now option one; attestation demoted to a fallback - RISC Zero: Groth16-wrapped receipts verify natively - Circom: both curves work; walkthrough stays on bls12381 to match the canonical verifier, and the curve-mismatch pitfall now says match circuit to verifier rather than avoid bn128 - Poseidon Merkle guidance updated; last-verified line added at top - References: official ZK/privacy docs pages, the UltraHonk verifier, and the bn254 SDK module (link checked) Closes #51.
|
| | BLS12-381 ops (G1/G2 add, mul, MSM, pairing check, hash-to-curve, Fr arithmetic) | [CAP-0059](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0059.md) | **Available** (Protocol 22+) | | ||
| | BN254 host functions | [CAP-0074](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0074.md) | Proposed — check current status | | ||
| | Poseidon/Poseidon2 hash | [CAP-0075](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0075.md) | Proposed — check current status | | ||
| | BN254 ops (G1 add/mul/MSM, pairing check, Fr arithmetic — `crypto::bn254`) | [CAP-0074](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0074.md) | **Available** (Protocol 25+) | |
There was a problem hiding this comment.
Fixed: the status table now splits BN254 into CAP-0074 base ops (G1 add/mul, pairing check, Protocol 25+) and CAP-0080 (G1 MSM, fr_add/sub/mul/pow/inv, on-curve checks, Protocol 26+).
| | RISC Zero (STARK → Groth16 wrap) | Groth16 | BN254 | Gated on CAP-0074 — attest meanwhile | | ||
| | Circom + snarkjs (`-p bls12381`) | Groth16 | BLS12-381 | ✅ via CAP-0059 (Protocol 22+) | | ||
| | Circom + snarkjs (default `bn128`) | Groth16 | BN254 | ✅ via CAP-0074 (Protocol 25+) | | ||
| | Noir + Barretenberg | UltraHonk | BN254 | ✅ via CAP-0074 (Protocol 25+) — needs the [rs-soroban-ultrahonk](https://github.com/NethermindEth/rs-soroban-ultrahonk) verifier contract | |
There was a problem hiding this comment.
Fixed: the Noir row now reads "via CAP-0074 + CAP-0080 (Protocol 26+)".
| ## Walkthrough: Noir (UltraHonk, on-chain verifiable since Protocol 25) | ||
|
|
||
| Noir's standard backend (Barretenberg) produces UltraHonk proofs over BN254 — neither the proof system nor the curve is on-chain verifiable on Stellar today. | ||
| Noir's standard backend (Barretenberg) produces UltraHonk proofs over BN254. Since Protocol 25 the curve is native (CAP-0074), and UltraHonk verification runs on-chain through [Nethermind's rs-soroban-ultrahonk](https://github.com/NethermindEth/rs-soroban-ultrahonk) verifier contract, whose only host calls are `env.crypto().bn254().g1_msm` and `pairing_check` — this is the stack OpenZeppelin's [Confidential Tokens developer preview](https://stellar.org/blog/developers/developer-preview-confidential-tokens-on-stellar) runs on (testnet). It is a young, community-maintained verifier: check its audit status and maturity before mainnet use. |
There was a problem hiding this comment.
Fixed: the paragraph now lists g1_msm, Fr arithmetic and pairing_check among the verifier's host calls, notes MSM/Fr come from CAP-0080, and states it needs Protocol 26+ and will fail to link on Protocol 25.
| Three ways to get a Noir statement on-chain, in order of preference: | ||
|
|
||
| Track CAP-0074 (BN254): when implemented, BN254 Groth16 verification becomes possible — but UltraHonk would additionally need a verifier implementation in-contract, so Groth16-based paths will land first. | ||
| 1. **On-chain UltraHonk verification** (Protocol 25+): deploy or call an [rs-soroban-ultrahonk](https://github.com/NethermindEth/rs-soroban-ultrahonk)-based verifier and submit `(proof, public inputs)` directly — trustless, no oracle. |
There was a problem hiding this comment.
Fixed: option 1 now reads "(Protocol 26+, CAP-0074 + CAP-0080)".
| | BN254 host functions | [CAP-0074](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0074.md) | Proposed — check current status | | ||
| | Poseidon/Poseidon2 hash | [CAP-0075](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0075.md) | Proposed — check current status | | ||
| | BN254 ops (G1 add/mul/MSM, pairing check, Fr arithmetic — `crypto::bn254`) | [CAP-0074](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0074.md) | **Available** (Protocol 25+) | | ||
| | Poseidon/Poseidon2 hash | [CAP-0075](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0075.md) | **Available** (Protocol 25+) | |
There was a problem hiding this comment.
Fixed: the row now reads "Poseidon/Poseidon2 permutation primitives (not complete hash functions)".
| - **Capability gating**: enable ZK flows only where required primitives are confirmed available; keep deterministic fallbacks and document the supported network/protocol matrix. | ||
|
|
||
| For Merkle-tree commitments (privacy pools, allowlists): until Poseidon (CAP-0075) lands, in-circuit-friendly hashing on-chain is expensive — design trees so the contract only needs root comparisons and membership proofs verified inside the SNARK. | ||
| For Merkle-tree commitments (privacy pools, allowlists): the Poseidon/Poseidon2 host functions (CAP-0075, Protocol 25+) make circuit-friendly hashing cheap on-chain, so contracts can recompute Poseidon Merkle roots and commitments directly. On pre-Protocol-25 targets, design trees so the contract only needs root comparisons and membership proofs verified inside the SNARK. |
There was a problem hiding this comment.
Fixed: the Merkle paragraph now states CAP-0075 exposes permutations only, and that guest-side sponge/compression plus matching field, t, d, round counts, MDS/diagonal, round constants, padding and domain separation are required — with the warning that mismatches yield roots differing from the circuit's or an insecure construction.
| ``` | ||
|
|
||
| On Stellar today, use the **attestation pattern** (as with Noir): verify the receipt off-chain — locally or via a proving service — and have an authorized attester submit the journal + attestation to your contract. Once CAP-0074 (BN254) is implemented, the Groth16-wrapped receipt becomes verifiable natively with a BN254 verifier contract mirroring the BLS12-381 one above; the `IMAGE_ID` (which program ran) and journal digest become public inputs. See the [RISC Zero docs](https://dev.risczero.com/api) for the wrapping workflow. | ||
| Since Protocol 25 (CAP-0074), the Groth16-wrapped receipt verifies **natively on-chain**: a BN254 verifier contract mirroring the BLS12-381 one above, with the `IMAGE_ID` (which program ran) and the journal digest as public inputs. See the [RISC Zero docs](https://dev.risczero.com/api) for the wrapping workflow. The attestation pattern remains a fallback for STARK-only receipts (no Groth16 wrap) or pre-Protocol-25 targets. |
There was a problem hiding this comment.
Fixed: the RISC Zero paragraph now states the five field inputs encode the control root (two halves), the receipt-claim digest (two halves) and the BN254 control ID, with the image ID and journal used to reconstruct that claim.
|
|
||
| ZK verification on Stellar. Capability is protocol- and SDK-version dependent — always verify CAP status, network version, and `soroban-sdk` host-function support before relying on a primitive. | ||
|
|
||
| > **Last verified against Protocol 27** (mainnet, July 2026). CAP-0074/0075 shipped in Protocol 25 "X-Ray" — if a doc tells you BN254 or Poseidon is "proposed", it predates that. |
There was a problem hiding this comment.
Fixed in the same PR: skills/standards/SKILL.md now lists CAP-0074 and CAP-0075 as Final / Protocol 25+ (in both places) and adds CAP-0080 as Implemented / Protocol 26+.
…rmutations, RISC Zero inputs Co-authored-by: kaankacar <103106776+kaankacar@users.noreply.github.com>
|
Re-verified every factual claim in this diff before merging — this one asserts a lot of specific protocol and API detail, so I checked each against primary sources rather than the PR description. CAP preambles (from The CAP-0074 / CAP-0080 split in the status table is exactly right — the host-function names in each CAP are: SDK surface compiled, not eyeballed. Built a contract against real Poseidon framing checks out. CAP-0075 says "host functions for Poseidon and Poseidon2 permutation primitives ... allowing developers to construct hash functions tailored to specific use cases", and the SDK's own migration note calls them "low-level ... permutation host functions". The parameter list the skill tells you to match (field, The UltraHonk claim. binop_fr!(Add, add, fr_add, +); // expands to env().crypto().bn254().fr_add(...)
pub fn pow(&self, rhs: u64) -> Self { self.env().crypto().bn254().fr_pow(self, rhs) }So the skill's wording ("host calls include The RISC Zero public-inputs correction is verbatim right, and it's the sharpest thing in this diff — let (a0, a1) = split_digest(control_root)?;
let (c0, c1) = split_digest(claim_digest)?;
let id_bn254_fr = fr_from_hex_string(&hex::encode(bn254_control_id))?;
Self::new_inner(&seal, &[a0, a1, c0, c1, id_bn254_fr], verifying_key)Five field elements: control root split in two, claim digest split in two, BN254 control ID. Not the image ID and journal digest, exactly as the skill now says. All six added/changed links resolve 200. No "proposed"/"not yet"/"gated on" wording survives except the deliberate mention inside the staleness marker. Merges cleanly against current One small change pushed in 1a1484f: bumped the marker from "July 2026" to "August 2026" to match when it was last actually verified — that line only earns its keep if the date is real. |
Three scenarios per skill plus cross-skill routing checks and an
off-topic negative control, in the {skills, query, expected_behavior}
format with optional machine_checkable assertions. evals/README.md
documents the tiers (compile checks, LLM-judged behavior, trigger
checks), the baseline process, and how to run a scenario; the root
README links it and documents the 500-line router convention.
Scenario expectations reflect current protocol reality rather than the
July proposal where they diverged: Noir/UltraHonk verifies on-chain
since Protocol 26 (#72), MPP Channel mode is now Session (#71), and
getLedgers depth is provider-retention dependent (#73).
Closes #51.
Applies @briwylde08's report, with every claim independently re-verified before writing:
cap-0074.mdandcap-0075.mdin stellar-protocol both read Status: Final, Protocol version: 25, and a livegetVersionInfoagainst mainnet RPC returns protocol 27 — the capabilities have been live for months while the skill still said "Proposed" and steered builders to attestation workarounds.env.crypto().bn254().g1_msmandpairing_check(per the project's milestone docs); it is the stack under OpenZeppelin's Confidential Tokens developer preview. The skill links it with an explicit young-verifier maturity caveat.crypto::bn254module page on docs.rs resolves (link checked before adding).Changes follow the issue's suggested fix list: status table rows to Available (Protocol 25+), all four toolchain rows now on-chain verifiable, the Noir walkthrough rewritten with on-chain UltraHonk as option one and attestation demoted to fallback, RISC Zero's Groth16 wrap marked natively verifiable, the Circom walkthrough and curve-mismatch pitfall reframed from "avoid bn128" to "match circuit curve to verifier", Poseidon Merkle guidance updated, and a "Last verified against Protocol 27" line at the top so future staleness is self-documenting. Frontmatter description and the site card updated to match.
Also picked up the issue's optional suggestion and added the official ZK and Privacy docs pages to references.