feat(m6/ec-c7): production Self VK (verified) + staging-proof capture instrumentation#34
Open
santisiri wants to merge 1 commit into
Open
feat(m6/ec-c7): production Self VK (verified) + staging-proof capture instrumentation#34santisiri wants to merge 1 commit into
santisiri wants to merge 1 commit into
Conversation
… + staging-proof capture instrumentation EC-C7 = flip the real Groth16 verifier on for Self proofs. Two deliverables; this lands #1 fully and wires up #2 (which needs a one-time human mock-passport scan). DELIVERABLE 1 — the production vc_and_disclose VK (DONE, adversarially verified): - crates/zkpoh/fixtures/self_prod_vkey.json: Self's real 21-signal vc_and_disclose V2 verifying key (protocol groth16, curve bn128, nPublic 21, IC length 22). Reconstructed from Self's on-chain Groth16 verifier and cross-checked BYTE-IDENTICAL across two independent primary sources — the GitHub-generated Verifier_vc_and_disclose.sol and the Celoscan-verified live Celo-mainnet deployment 0x0A57C317800865194496763377d25CA2082DB649 (reported byte-identical to the Celo-Sepolia staging verifier 0x7C2FBA7F...). The snarkjs G2 c0/c1 swap was PROVEN correct by reducing vk_gamma_2 to the canonical BN254 G2 generator; all 4 fixed points + 22 IC points pass on-curve + prime-order-subgroup checks. This supersedes the prior blocker (Self's S3 ceremony bucket 403s; the stale 20-signal legacy VK is rejected). - crates/zkpoh/tests/self_prod_vk_derisk.rs: proves the real VK loads through our exact pin pipeline — SnarkjsVk::to_pinned -> to_canonical_bytes -> from_canonical_bytes(Validate::Yes) -> Groth16Verifier::from_vk_bytes, reporting the confirmed arity (nPublic 21, 936-byte canonical VK). (Does NOT yet assert a proof verifies — that needs the captured staging proof.) DELIVERABLE 2 — capture instrumentation (ready; awaits one scan): - apps/wallet/app/api/self-verify/capture.ts + route.ts wiring: a dev-only capture side-channel, a NO-OP unless UBI2_SELF_CAPTURE_DIR is set (never touches the relay's trust boundary or response). On a genuine Self STAGING scan it persists the verbatim {proof, publicSignals} plus a decoded meta file (each public slot as decimal AND 0x-padded 32-byte scalar) for reconciling UBI2_SELF_SCOPE + the accepted roots. - docs/ec-c7-capture-runbook.md: the exact human steps (Self mock passport, tunnel, scan), the off-chain snarkjs GO/NO-GO gate, and the four mechanical edits to pin+flip once a proof is captured. zkpoh suite green (5 tests incl. the new de-risk); wallet typecheck green; capture logic verified (32-byte BE hex correct, no-op when disabled). No consensus/runtime code changed — MockZkVerifier remains the devnet default; the real flip is still gated on the captured proof. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
EC-C7 — real Self verifier: production VK (verified) + capture instrumentation
EC-C7 flips ubi2 from the devnet
MockZkVerifierto the real on-chainGroth16Verifierfor Self passport proofs. Two deliverables; this PR lands #1 fully and wires up #2.✅ Deliverable 1 — the production
vc_and_discloseVK (adversarially verified)Prior blocker: Self's S3 ceremony bucket 403s and the
.zkeyis uncommitted, so we only had a synthetic layout-lock VK. Resolved by extracting the VK from Self's on-chain Groth16 verifier:crates/zkpoh/fixtures/self_prod_vkey.json— Self's real 21-signal V2 VK (groth16/bn128, nPublic 21, IC 22), cross-checked byte-identical across two independent primary sources: the GitHub-generatedVerifier_vc_and_disclose.soland the Celoscan-verified live Celo-mainnet deployment0x0A57C317…(reported byte-identical to the Celo-Sepolia staging verifier0x7C2FBA7F…).vk_gamma_2to the canonical BN254 G2 generator; all 4 fixed points + 22 IC points pass on-curve/subgroup checks; the stale 20-signal legacy VK is rejected.crates/zkpoh/tests/self_prod_vk_derisk.rsproves the real VK loads through our exact pin pipeline at arity-21 (936-byte canonical VK). It does not yet assert a proof verifies — that needs the captured proof.⏳ Deliverable 2 — capture a genuine staging proof (instrumented; needs one human scan)
Self mock-passport registration runs in a phone TEE and can't be scripted headlessly. This PR wires the capture so a single scan yields a reusable fixture:
apps/wallet/app/api/self-verify/capture.ts(+ route wiring) — a dev-only side-channel, a no-op unlessUBI2_SELF_CAPTURE_DIRis set, that never touches the relay's trust boundary. On a genuine staging scan it persists{proof, publicSignals}+ a decoded meta file (each slot as decimal and 0x-padded 32-byte scalar) for reconcilingUBI2_SELF_SCOPE+ the accepted roots.docs/ec-c7-capture-runbook.md— the exact human steps, the off-chain snarkjs GO/NO-GO gate, and the four mechanical pin+flip edits.Safety
No consensus/runtime code changed —
MockZkVerifierremains the devnet default; the real flip stays gated on the captured proof. zkpoh suite green (5 tests incl. the new de-risk); wallet typecheck green; capture logic verified (32-byte BE hex, no-op when disabled).🤖 Generated with Claude Code