feat!: ownership proof (wip-103) correctness improvements - #885
feat!: ownership proof (wip-103) correctness improvements#885paolodamico wants to merge 30 commits into
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4af6914. Configure here.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4af69140b4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
Pull request overview
Implements Least Authority audit follow-ups for WIP-103 by making the Ownership Proof circuit and Rust APIs explicitly bind proofs to a verifier-supplied context, moving expected_commitment to a public input (and constraining it in-circuit), and updating fixtures/CI to keep Noir artifacts and examples in sync.
Changes:
- Noir ownership-proof circuit: add public
expected_commitment+context, assert commitment equality in-circuit, and bind(expected_commitment, nonce, context)into the signed message. - Rust proof/authenticator plumbing: thread
contextthrough proving & verification, centralize the signed-message digest, and add pre-proving input validation + fixtures. - Spec + CI: expand WIP-103 with explicit I/O + constraints; add
nargo execute --pedantic-solvingin CI.
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/WIPs/wip-103.md | Updates WIP-103 spec to match new public inputs/constraints and nonce/context rules. |
| crates/proof/src/ownership_proof.rs | Adds context + expected_commitment to verification inputs, centralizes message_digest, adds input validation + tests. |
| crates/proof/src/nullifier_proof/errors.rs | Extends shared ProofInputError with new variants used by ownership input validation. |
| crates/proof/src/lib.rs | Adds a test-only fixtures module for shared circuit examples/tests. |
| crates/proof/src/fixtures.rs | Introduces a fixture builder + deterministic Prover.toml renderer with update gate. |
| crates/proof/src/circuit_inputs.rs | Extends ownership circuit input struct with expected_commitment and context. |
| crates/proof/noir/ownership-proof/src/types.nr | Renames/clarifies types (e.g., leaf_index, commitment_blinder) and removes output struct. |
| crates/proof/noir/ownership-proof/src/main.nr | Updates circuit ABI and constraints; adds extensive negative tests for binding/validation. |
| crates/proof/noir/ownership-proof/src/constants.nr | Renames circuit domain separator constant to DS_WIP_103. |
| crates/proof/noir/ownership-proof/src/commitment.nr | Updates commitment/message hashing to t=4 with context binding; adds tests. |
| crates/proof/noir/ownership-proof/Prover.toml | Updates committed example inputs to new ABI and regenerated signature/material. |
| crates/proof/Cargo.toml | Adjusts packaged include list (drops tests/**/*). |
| crates/authenticator/src/prove.rs | Adds context parameter and signs the new (expected_commitment, nonce, context) digest. |
| crates/authenticator/Cargo.toml | Removes direct poseidon2 dependency (digest now centralized in proof crate). |
| Cargo.lock | Removes the no-longer-needed poseidon2 dependency edge. |
| .github/workflows/noir-ci.yml | Adds nargo execute --pedantic-solving for ownership-proof in CI. |
Suppressed comments (1)
docs/WIPs/wip-103.md:115
- The Context section uses "MUST constraint" (verb) and again uses "Verifies" instead of "Verifiers". This is a grammatical error in a normative sentence.
The `context` is the mechanism by which a verifier binds a specific proof to a specific requested operation. The verifier MUST constraint the use of Ownership Proofs to specific operations and assign such operations with a unique context. For example, renewing a credential and deleting a credential are two different contexts. The verifier MUST provide the `context` when requesting a proof and MUST verify the provided `context` is valid for the explicit operation being executed. Verifies MAY use modulo reduction to lower arbitrary bytes as a field element.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Codex Review: Didn't find any major issues. Already looking forward to the next diff. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |

Context
Following the Least Authority audit of WIP-103 from July 28, 2026, implementing a number of improvements.
Circuit changes
contextwhich is provided by the verifier. Particularly for the use case of provingsubownership, specifying a specific context to which a proof is bound is useful to reduce the surface area of mis-implementednoncelogic. For example, the issuer will request a proof for thecontext = b"delete credential", preventing accidental use of such proof for e.g. renewing a credential. We don't expect users to see this context, but it's added as a defense-in-depth mechanism to prevent cross-context use. Thiscontextis bound in the authenticator's signature. Resolution to Suggestion 3.expected_commitmentis now an input instead of an output (as mandated by the spec). This reduces surface area for mis-implementation on the verifier side as the equality between the computed commitment and the expected one is done in the circuit.nonce, this isn't actually needed because thenonceis already used in the message for the signature.root->merkle_root,commitment_r->commitment_blinder)Other changes
Prover.tomlfixture dynamically as well as a full update with real inputs for circuit execution. Resolution to Suggestion 1.Spec Updates
These updates are introduced as a Resolution to Suggestion 2.
Note
High Risk
Changes the ownership ZK circuit and signing message format (breaking for verifiers/provers) in authentication-critical crypto; incorrect rollout would reject valid proofs or weaken binding if mismatched.
Overview
Breaking change to the WIP-103 Ownership Proof circuit and Rust APIs (authenticator, proving, verification).
The circuit now takes
expected_commitmentandcontextas public inputs (commitment is checked in-circuit instead of being an output), binds the authenticator signature toPoseidon2(DS_WIP_103, expected_commitment, nonce, context), rejects zerononce/context, and drops the old dummynonceconstraint. Witness/public naming is aligned (merkle_root,commitment_blinder,leaf_index).Rust mirrors this: shared
message_digest, pre-provecheck_ownership_input_validity,prove_credential_sub/verify_ownership_prooftakecontext, andOwnershipProofCircuitInputcarriesexpected_commitment. Noir CI addsnargo execute --pedantic-solving;Prover.tomlis generated from a shared fixture test. WIP-103 documents inputs, constraints, nonce/context rules. Large negative tests cover tampering, keys, and Merkle paths.Reviewed by Cursor Bugbot for commit e366c15. Bugbot is set up for automated code reviews on this repo. Configure here.