apiBillingV2 — trusted setup maturity & artifact rotation
Phase-2 in-circuit binding (binding_version: bn128-poseidon8-v1) is the right architecture for cryptographic commitment binding: the Groth16 proof ties public_commitments to a single public signal independent of the Ed25519 attestation wrapper.
Pilot vs adversarial production: today's deployed artifacts are pilot-grade. The circuit compiles and verifies end-to-end, manifests pin hashes at boot, and pilot tests cover tamper rejection — but the Groth16 Phase-2 contribution was a single dev entropy round, not a multi-party ceremony. Before relying on this under adversarial production trust, run a proper MPC and publish a rotation story.
Current state
| Item | Status |
|---|---|
| Circuit | zk-cp/circuits/apiBillingV2.circom → apiBillingV2 |
| Binding | Poseidon8 over 8 field-images of public_commitments |
| Manifest | verifier-api/circuits/apiBillingV2/ARTIFACT_MANIFEST.json |
| Ceremony type | multi_party_computation (3 Phase-2 contributors, Phase-1 skipped — pinned pot14_final.ptau) |
| Transcript | zk-cp/build/apiBillingV2/mpc_transcript_apiBillingV2.json |
| One-shot rerun | bash zk-cp/scripts/mpc-api-billing-v2.sh |
Honest limit: contributors in the default script use independent random entropy on one machine (CI-friendly). For adversarial production trust, run the same script with 3+ independent operators (each supplies entropy on their own host) and publish the transcript + hashes.
Target: multi-party ceremony
Reuse the repo's standard MPC flow (trusted-setup-mpc.md) with apiBillingV2 paths:
# 1. Compile R1CS + WASM (if sources changed)
bash zk-cp/scripts/compile-api-billing-v2.sh # dev only — MPC replaces zkey/vkey
# 2. Phase-2 MPC (reuse pinned pot14_final.ptau)
export MPC_CONTRIBUTORS=3
export MPC_MIN_CONTRIBUTORS=2
export MPC_CIRCUIT_NAME=apiBillingV2
export MPC_R1CS_PATH=zk-cp/build/apiBillingV2/apiBillingV2.r1cs
export MPC_OUTPUT_DIR=zk-cp/build/apiBillingV2
export MPC_PTAU_FINAL=zk-cp/build/pot14_final.ptau
export MPC_SKIP_PHASE1=1
bash protocol/scripts/mpc-snarkjs-ceremony.shDeliverables to publish:
mpc_transcript_apiBillingV2.json+mpc_ceremony.log- SHA-256 of final
apiBillingV2_0001.zkey,apiBillingV2.vkey.json,apiBillingV2_js/apiBillingV2.wasm - Updated
ARTIFACT_MANIFEST.jsonwithceremony.type: multi_party_mpcandtranscript_available: true
Merge transcript into the per-circuit manifest (adapt paths from trusted-setup-mpc.md § Post-ceremony):
cd protocol
node scripts/post-mpc-manifest.js \
--transcript ../zk-cp/build/apiBillingV2/mpc_transcript_apiBillingV2.json \
--manifest ../verifier-api/circuits/apiBillingV2/ARTIFACT_MANIFEST.json \
--circuit-dir ../zk-cp/build/apiBillingV2 \
--refresh-hashesMirror artifacts to all resolver paths (zk-cp/build/apiBillingV2/, verifier-api/circuits/apiBillingV2/, public/circuits/apiBillingV2/, protocol/packages/vdi-prover/circuits/apiBillingV2/).
Artifact rotation story (production)
Rotation is a versioned governance event, never a silent overwrite (see security-model.md § Artifact Lifecycle).
What rotates
| Artifact | Issuer uses | Verifier pins |
|---|---|---|
apiBillingV2_0001.zkey | Prover at attest (generateInCircuitBillingProof) | — |
apiBillingV2.vkey.json | Embedded in attestation.billing_proof.vkey | vkey_hash on each proof |
| WASM / R1CS | Witness + prove | circuit_hash on each proof |
Each issued attestation carries billing_proof.vkey_hash and billing_proof.circuit_hash. Verifiers check Groth16 against the embedded vkey; optional allow-lists can reject unknown hashes (verifyInCircuitBillingProof({ allowedVkeyHashes })).
Rotation procedure
- Freeze circuit — bump
circuit.versionin manifest only if.circomchanges; otherwise rotate keys only. - Run MPC — new zkey/vkey; publish transcript.
- Update manifests — refresh
artifacts.*.sha256andceremonymetadata in all mirror directories. - Dual-verify window — deploy API with both old and new vkey hashes accepted for verification (e.g. 30–90 days) so historical attestations remain valid.
- Cutover — new attestations use new zkey only; announce deprecation date for old
vkey_hash. - Revoke old pin — remove old hash from allow-list; old attestations still verify offline with embedded vkey (forward-compatible by design).
Boot-time enforcement
verifier-api validates ARTIFACT_MANIFEST.json on startup (artifactValidator.js). A deploy with mismatched on-disk hashes refuses to prove — catch drift before issuance.
Customer / auditor message
Phase-2 proofs bind billing commitments in-circuit. Groth16 soundness depends on the setup ceremony: pilot artifacts use dev entropy; production will publish an MPC transcript and pinned hashes before adversarial trust claims. Rotation is announced via manifest version +
vkey_hash; historical bundles remain verifiable with their embedded keys.
Readiness checklist (before adversarial trust)
- [ ] Multi-party Phase-2 ceremony complete (
MPC_MIN_CONTRIBUTORSmet) - [ ] Transcript JSON + hashes published alongside manifest
- [ ]
ARTIFACT_MANIFEST.jsonceremony.transcript_available: true - [ ] Rotation runbook exercised once (staging cutover with dual-verify window)
- [ ] Pilot packet updated with ceremony date + contributor list
Until then: architecture ready, ceremony maturing.
