Skip to content

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

ItemStatus
Circuitzk-cp/circuits/apiBillingV2.circomapiBillingV2
BindingPoseidon8 over 8 field-images of public_commitments
Manifestverifier-api/circuits/apiBillingV2/ARTIFACT_MANIFEST.json
Ceremony typemulti_party_computation (3 Phase-2 contributors, Phase-1 skipped — pinned pot14_final.ptau)
Transcriptzk-cp/build/apiBillingV2/mpc_transcript_apiBillingV2.json
One-shot rerunbash 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:

bash
# 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.sh

Deliverables to publish:

  1. mpc_transcript_apiBillingV2.json + mpc_ceremony.log
  2. SHA-256 of final apiBillingV2_0001.zkey, apiBillingV2.vkey.json, apiBillingV2_js/apiBillingV2.wasm
  3. Updated ARTIFACT_MANIFEST.json with ceremony.type: multi_party_mpc and transcript_available: true

Merge transcript into the per-circuit manifest (adapt paths from trusted-setup-mpc.md § Post-ceremony):

bash
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-hashes

Mirror 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

ArtifactIssuer usesVerifier pins
apiBillingV2_0001.zkeyProver at attest (generateInCircuitBillingProof)
apiBillingV2.vkey.jsonEmbedded in attestation.billing_proof.vkeyvkey_hash on each proof
WASM / R1CSWitness + provecircuit_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

  1. Freeze circuit — bump circuit.version in manifest only if .circom changes; otherwise rotate keys only.
  2. Run MPC — new zkey/vkey; publish transcript.
  3. Update manifests — refresh artifacts.*.sha256 and ceremony metadata in all mirror directories.
  4. 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.
  5. Cutover — new attestations use new zkey only; announce deprecation date for old vkey_hash.
  6. 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_CONTRIBUTORS met)
  • [ ] Transcript JSON + hashes published alongside manifest
  • [ ] ARTIFACT_MANIFEST.json ceremony.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.

Verification keys are embedded in attestations. The verifier is open source.