Skip to content

feat: impl proof circuits#1

Merged
Ugo-X merged 4 commits intomainfrom
proof-circuits
Sep 10, 2025
Merged

feat: impl proof circuits#1
Ugo-X merged 4 commits intomainfrom
proof-circuits

Conversation

@JoE11-y
Copy link
Copy Markdown
Contributor

@JoE11-y JoE11-y commented Sep 9, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a Noir-based proof circuit to verify trade authorization privately (nullifier hashing and ECDSA checks).
    • Added CLI scripts to generate prover inputs and compute the required hash for proofs.
    • Enabled end-to-end proving and verification via Barretenberg/Noir tooling.
  • Documentation

    • Added a comprehensive README with prerequisites, setup, and step-by-step usage.
  • Chores

    • Updated ignore rules.
    • Added required dependencies for Noir and Barretenberg.
    • Removed obsolete manifests and sample code from the previous prototype.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Sep 9, 2025

Walkthrough

Replaces a removed Rust app with a new Noir-based proof circuit under apps/proof_circuit, adds associated scripts and README, updates root package.json with JS deps for hashing, and updates .gitignore. The new circuit verifies ECDSA recoveries and a Poseidon2-based nullifier derived from a selected signature.

Changes

Cohort / File(s) Summary
Repo housekeeping
/.gitignore, /package.json
Ignore /target and Prover.toml. Add JS deps: @aztec/bb.js, @noir-lang/noir_js, and dev @types/node.
Remove Rust proof-circuit app
apps/proof-circuit/Cargo.toml, apps/proof-circuit/package.json, apps/proof-circuit/src/main.rs
Delete Rust crate and Node manifest; remove “Hello, world!” entrypoint.
Add Noir proof circuit
apps/proof_circuit/Nargo.toml, apps/proof_circuit/src/main.nr, apps/proof_circuit/src/utils.nr, apps/proof_circuit/README.md
Add Noir project: Nargo manifest with deps (ecrecover, poseidon). Implement main circuit verifying nullifier and two ECDSA recoveries; add pubkey split utility and documentation.
Prover input tooling
apps/proof_circuit/scripts/generate-inputs.sh, apps/proof_circuit/scripts/hash.ts, apps/proof_circuit/scripts/inputs.txt
Add script to build Prover.toml from inputs, TS tool to Poseidon-hash reduced RS bytes, and example inputs template.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Bash as scripts/generate-inputs.sh
  participant TS as scripts/hash.ts (Poseidon2)
  participant Noir as apps/proof_circuit (Noir)

  User->>Bash: Run generate-inputs.sh
  Bash->>Bash: Read scripts/inputs.txt
  Bash->>TS: hash(sigSelected) via CLI
  TS->>TS: reduceRS(rs) mod P
  TS-->>Bash: Poseidon2Hash([Fr(rsReduced)])
  Bash->>Bash: Build Prover.toml (hex->dec arrays, flags)
  Bash-->>User: Prover.toml written
  User->>Noir: nargo execute (Prover.toml)
  Noir->>Noir: Poseidon2([sig_field]) == nullifier_hash
  Noir->>Noir: split_uncompressed_pub_key(...)
  Noir->>Noir: ecrecover(ad_creator) == ad_creator
  Noir->>Noir: ecrecover(bridger) == bridger
  Noir-->>User: witness / proof artifacts
Loading
sequenceDiagram
  autonumber
  participant Caller as Public Inputs
  participant Circuit as main.nr
  participant Utils as utils.nr
  participant EC as dep::ecrecover
  participant Hash as poseidon2

  Caller->>Circuit: nullifier_hash, ad_creator, bridger, msg_hash, ad_contract,<br/>ad_creator_pub_key, ad_creator_sig, bridger_pub_key, bridger_sig
  Circuit->>Circuit: Select sig_field by ad_contract
  Circuit->>Hash: Poseidon2([sig_field])
  Hash-->>Circuit: expected_nullifier_hash
  Circuit->>Circuit: assert expected_nullifier_hash == nullifier_hash
  Circuit->>Utils: split_uncompressed_pub_key(ad_creator_pub_key)
  Utils-->>Circuit: (x1, y1)
  Circuit->>EC: ecrecover(x1, y1, ad_creator_sig, msg_hash)
  EC-->>Circuit: expected_ad_creator
  Circuit->>Circuit: assert ad_creator == expected_ad_creator
  Circuit->>Utils: split_uncompressed_pub_key(bridger_pub_key)
  Utils-->>Circuit: (x2, y2)
  Circuit->>EC: ecrecover(x2, y2, bridger_sig, msg_hash)
  EC-->>Circuit: expected_bridger
  Circuit->>Circuit: assert bridger == expected_bridger
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “feat: impl proof circuits” succinctly reflects the main purpose of the changeset—introducing and wiring up proof circuit functionality—and follows conventional commit prefixes for feature additions.

Poem

I thump my paws on circuit ground,
A nullifier’s hush, no secrets found.
With Poseidon’s swirl and keys in two,
I sniff the hash, recover who.
Rust hops out, Noir hops in—
Scripts brew proofs; let trials begin! 🐇✨

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch proof-circuits

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
.gitignore (1)

3-3: Ignore all build artifacts under target (keep Verifier in a proper source dir instead).

Only ignoring /target/vk still commits large compiled blobs. Prefer ignoring the whole app target dir and track Verifier.sol in a stable contracts/ path if you need it versioned.

 node_modules
-
-/target/vk
+apps/proof_circuit/target/
+# If you want to keep a placeholder:
+!apps/proof_circuit/target/.gitkeep
apps/proof_circuit/Nargo.toml (1)

4-4: Fill or remove empty authors.

Empty author metadata is noise. Either drop the field or populate it.

 [package]
 name = "proof_circuit"
 type = "bin"
-authors = [""]
+# authors = ["Your Name <you@example.com>"]
apps/proof_circuit/target/proof_circuit.json (1)

1-1: Don’t commit heavy compiled artifacts and local absolute paths.

This JSON includes debug_symbols and absolute local paths (e.g., /home/blockyj/...) which add bloat and leak environment info. Consider excluding apps/proof_circuit/target/*.json from VCS; regenerate during CI instead.

I can add a minimal build step to CI that compiles the circuit and uploads artifacts if needed.

apps/proof_circuit/target/Verifier.sol (3)

770-786: Pairing precompile comments are misleading; verify G2 limb ordering.

The constants here are G2 Fp2 coordinates, but comments say “Fixed G1 point” / “G1 point from VK”. Please correct comments and double-check the Fp2 limb order (bn128 pairing expects [x_im, x_re, y_im, y_re]).

If these constants came from the barretenberg generator, link or paste the source to confirm limb order.


3-3: Two pragma directives — keep one.

Having both >=0.8.21 and ^0.8.27 is redundant; the intersection is ^0.8.27. Keep a single pragma at the top.

-pragma solidity >=0.8.21;
+pragma solidity ^0.8.27;
...
-pragma solidity ^0.8.27;

Also applies to: 127-127


1633-1635: Gas: batch-invert denominators.

You already note “batch invert later?” — doing a Montgomery batch inversion here saves many modexp calls.

I can wire a small batch inversion helper on Fr using the modexp precompile to reduce calls.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9219084 and 133f7c2.

📒 Files selected for processing (8)
  • .gitignore (1 hunks)
  • apps/proof-circuit/Cargo.toml (0 hunks)
  • apps/proof-circuit/package.json (0 hunks)
  • apps/proof-circuit/src/main.rs (0 hunks)
  • apps/proof_circuit/Nargo.toml (1 hunks)
  • apps/proof_circuit/src/main.nr (1 hunks)
  • apps/proof_circuit/target/Verifier.sol (1 hunks)
  • apps/proof_circuit/target/proof_circuit.json (1 hunks)
💤 Files with no reviewable changes (3)
  • apps/proof-circuit/package.json
  • apps/proof-circuit/src/main.rs
  • apps/proof-circuit/Cargo.toml
🔇 Additional comments (2)
apps/proof_circuit/src/main.nr (1)

3-22: LGTM: concise dual-sig verification against public addresses and msg_hash.

Inputs and assertions line up with dep::ecrecover’s semantics (verify with provided pubkey, derive ETH address).

Please confirm the msg_hash you pass in is the exact 32-byte digest expected by std::ecdsa_secp256k1::verify_signature (no Ethereum signed message prefix applied unless your off-chain signer used it). If you want, I can add a helper that hashes raw bytes inside the circuit to avoid mismatch.

apps/proof_circuit/target/Verifier.sol (1)

1567-1598: Add CI checks for PROOF_SIZE and publicInputsSize
PROOF_SIZE is hard-coded to 456 and vk.publicInputsSize to 50 in Verifier.sol—add CI assertions to ensure these match your ZK circuit JSON (e.g. proof_circuit.json). For example:

# verify proof element count
jq '.proof | length' apps/proof_circuit/target/proof_circuit.json | grep -qx '456'
# verify public-inputs count
jq '.public_inputs | length' apps/proof_circuit/target/proof_circuit.json | grep -qx '50'

Comment thread apps/proof_circuit/Nargo.toml
Comment thread apps/proof_circuit/target/Verifier.sol Outdated
Comment thread apps/proof_circuit/target/Verifier.sol Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (6)
apps/proof_circuit/src/utils.nr (1)

1-11: Assert uncompressed pubkey prefix to guard misuse.

Add a simple constraint so invalid keys fail early instead of propagating bad coordinates.

 pub fn split_uncompressed_pub_key(pub_key: [u8; 65]) -> ([u8; 32], [u8; 32]) {
     let mut pub_key_x: [u8; 32] = [0; 32];
     let mut pub_key_y: [u8; 32] = [0; 32];

+    // Expect uncompressed secp256k1 pubkey (0x04 || X[32] || Y[32])
+    assert(pub_key[0] == 4);
+
     for i in 0..32 {
         pub_key_x[i] = pub_key[i + 1];
         pub_key_y[i] = pub_key[i + 32 + 1];
     }
     (pub_key_x, pub_key_y)
 }
package.json (1)

12-19: Ensure tooling can run TypeScript scripts and versions are compatible.

  • You added a TS script (hash.ts) but no runner. Add tsx (or ts-node) so generate-inputs.sh can execute it reliably.
  • Verify @aztec/bb.js@^0.87.0 is compatible with @noir-lang/noir_js@1.0.0-beta.9 for Poseidon2 APIs.

Proposed additions:

   "packageManager": "pnpm@10.10.0",
   "dependencies": {
     "@aztec/bb.js": "^0.87.0",
     "@noir-lang/noir_js": "1.0.0-beta.9"
   },
   "devDependencies": {
-    "@types/node": "^24.3.1"
+    "@types/node": "^24.3.1",
+    "tsx": "^4.16.0",
+    "typescript": "^5.5.0"
   }

Optionally expose a script:

   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "hash:poseidon": "tsx apps/proof_circuit/scripts/hash.ts"
   }
apps/proof_circuit/scripts/hash.ts (1)

21-31: Minor: avoid abrupt process.exit in library-ish code.

Since this file both exports a function and runs as a CLI, prefer setting process.exitCode and returning to keep it friendlier for programmatic use. Not blocking.

-      process.stdout.write(result);
-      process.exit(0);
+      process.stdout.write(result);
+      process.exitCode = 0;
 ...
-      process.exit(1);
+      process.exitCode = 1;
apps/proof_circuit/scripts/generate-inputs.sh (2)

7-12: Harden key parsing and avoid multiple matches.

Quote the grep pattern, allow leading spaces, and take the first match to avoid unexpected multiple-line captures.

Apply this diff:

-extract_value() {
+extract_value() {
     local key=$1
-    # Extract the part inside quotes after the equals sign
-    grep "^$key\s*=" "$input_file" | sed -E 's/^[^=]+= *"(.*)"/\1/'
+    # Extract the part inside quotes after the equals sign (first match only)
+    grep -E "^[[:space:]]*${key}[[:space:]]*=" "$input_file" | head -n1 | sed -E 's/^[^=]+= *"(.*)".*$/\1/'
 }

70-76: Outdated comment and missing normalization note.

Comment mentions “expected_address” (not present). Update to reflect actual vars and that signatures are normalized before hashing.

Apply this diff:

-# Strip 0x from everything except expected_address
+# Strip 0x from hex blob inputs (addresses remain as-is; converted to Field later)
apps/proof_circuit/src/main.nr (1)

17-26: Ensure the nullifier hashing matches preimage semantics.

You reduce 64 bytes to a single Field via Field::from_be_bytes(...) then hash one element. If the goal is “hash the exact 64 signature bytes,” consider hashing two field limbs (first 32, next 32) to avoid reduction ambiguity. Also confirm from_be_bytes accepts 64 bytes in this Noir version.

Example refactor (conceptual):

let (a, b) = if ad_contract {
    (Field::from_be_bytes(bridger_sig[0..32]), Field::from_be_bytes(bridger_sig[32..64]))
} else {
    (Field::from_be_bytes(ad_creator_sig[0..32]), Field::from_be_bytes(ad_creator_sig[32..64]))
};
let expected_nullifier_hash = poseidon2::Poseidon2::hash([a, b], 2);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 133f7c2 and 13361b4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • .gitignore (1 hunks)
  • apps/proof_circuit/Nargo.toml (1 hunks)
  • apps/proof_circuit/README.md (1 hunks)
  • apps/proof_circuit/scripts/generate-inputs.sh (1 hunks)
  • apps/proof_circuit/scripts/hash.ts (1 hunks)
  • apps/proof_circuit/scripts/inputs.txt (1 hunks)
  • apps/proof_circuit/src/main.nr (1 hunks)
  • apps/proof_circuit/src/utils.nr (1 hunks)
  • package.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • apps/proof_circuit/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/proof_circuit/Nargo.toml
  • .gitignore
🧰 Additional context used
🪛 Shellcheck (0.10.0)
apps/proof_circuit/scripts/generate-inputs.sh

[error] 2-2: The shebang must be on the first line. Delete blanks and move comments.

(SC1128)


[warning] 27-27: The surrounding quotes actually unquote this. Remove or escape them.

(SC2027)


[warning] 27-27: Quote this to prevent word splitting.

(SC2046)

🔇 Additional comments (4)
apps/proof_circuit/scripts/inputs.txt (1)

7-7: Confirm boolean parsing of ad_contract.

If generate-inputs.sh sources this file in bash, spaces around = and quoting booleans will not parse. If it’s parsed manually, you’re fine. Please confirm.

If bash-sourced, prefer:

-ad_contract = "false"
+ad_contract=false
apps/proof_circuit/scripts/hash.ts (1)

9-10: No changes needed for hex formatting
Fr.fromString accepts both 0x-prefixed hex and decimal strings, and nullifierHash.toString() returns a 0x-prefixed hex string, which aligns with Noir’s expected input format.

apps/proof_circuit/scripts/generate-inputs.sh (1)

78-80: Confirm signature format assumptions.

We assume 65-byte ECDSA (r||s||v) with v last and 1 byte. If EIP-2098 (64-byte compact) appears, this truncation breaks inputs. Verify inputs.txt format or gate with a length check.

Do you want me to add a length guard that errors unless signatures are 130 hex chars (after 0x), and optionally support EIP-2098?

apps/proof_circuit/src/main.nr (1)

28-37: Confirm ecrecover API expectations (no v parameter).

You pass (pubkey_x, pubkey_y, sigRS, msg_hash). If the library expects (sigRSV, msg_hash) to recover pubkey, this will mis-verify. Double-check dep version/API.

Would you like me to look up the exact ecrecover Noir crate API you’re pinning and adjust accordingly?

Comment thread apps/proof_circuit/scripts/generate-inputs.sh
Comment thread apps/proof_circuit/scripts/generate-inputs.sh
Comment thread apps/proof_circuit/scripts/generate-inputs.sh
Comment thread apps/proof_circuit/scripts/generate-inputs.sh
Comment thread apps/proof_circuit/scripts/generate-inputs.sh
Comment thread apps/proof_circuit/scripts/hash.ts
Comment thread apps/proof_circuit/scripts/inputs.txt
Comment thread apps/proof_circuit/src/main.nr
@Ugo-X Ugo-X merged commit ed6a506 into main Sep 10, 2025
1 check passed
JoE11-y added a commit that referenced this pull request Jan 10, 2026
@coderabbitai coderabbitai bot mentioned this pull request Apr 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants