Skip to content

Add BN254 and BLS12-381 Groth16 verifier (Circom, Gnark, and Arkworks) - #396

Open
mysteryon88 wants to merge 16 commits into
stellar:mainfrom
mysteryon88-forks:main
Open

Add BN254 and BLS12-381 Groth16 verifier (Circom, Gnark, and Arkworks)#396
mysteryon88 wants to merge 16 commits into
stellar:mainfrom
mysteryon88-forks:main

Conversation

@mysteryon88

Copy link
Copy Markdown

What

Added usage examples for the Soroban Groth16 verifier contract generator implemented in this project, using proofs and verification keys produced by Circom, Gnark, and Arkworks.

Why

These examples demonstrate how the generator can be used with popular ZK frameworks to generate Soroban-compatible verifier contracts and make the intended workflow clearer for users.

Known limitations

  • The implementation is based on the Soroban Groth16 verifier example from the Stellar repository
  • The generator and resulting contracts have not undergone a security audit

Copilot AI review requested due to automatic review settings January 27, 2026 08:25
@socket-security

socket-security Bot commented Jan 27, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: cargo zerocopy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?cargo/ark-std@0.6.0cargo/ark-ec@0.6.0cargo/ark-relations@0.6.0cargo/ark-crypto-primitives@0.6.0cargo/ark-groth16@0.6.0cargo/soroban-sdk@27.0.0cargo/soroban-ledger-snapshot@27.0.0cargo/soroban-sdk@27.0.2cargo/rand@0.8.5cargo/rand@0.7.3cargo/ark-ec@0.4.2cargo/proptest@1.5.0cargo/ark-ec@0.5.0cargo/ark-std@0.5.0cargo/alloy-sol-types@1.3.1cargo/zerocopy@0.8.55

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore cargo/zerocopy@0.8.55. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds example inputs and generated Soroban verifier contract crates demonstrating how to use the Soroban Groth16 verifier generator with Circom- and Gnark-produced artifacts.

Changes:

  • Added Circom and Gnark example proof/VK JSON fixtures under groth16_verifier_gen/data/.
  • Added two generated Soroban verifier contract crates (verifier, gnark_verifier) with basic tests.
  • Added groth16_verifier_gen workspace scaffolding/docs (README, workspace Cargo files, gitignore), plus an unrelated account/Cargo.lock update.

Reviewed changes

Copilot reviewed 14 out of 16 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
groth16_verifier_gen/data/gnark/verification_key.json Adds Gnark verification key fixture for generator usage/testing.
groth16_verifier_gen/data/gnark/proof.json Adds Gnark proof fixture for generator usage/testing.
groth16_verifier_gen/data/circom/verification_key.json Adds Circom verification key fixture for generator usage/testing.
groth16_verifier_gen/data/circom/public.json Adds Circom public inputs fixture for generator usage/testing.
groth16_verifier_gen/data/circom/proof.json Adds Circom proof fixture for generator usage/testing.
groth16_verifier_gen/contracts/verifier/src/test.rs Adds tests for the generated verifier contract (Circom fixtures).
groth16_verifier_gen/contracts/verifier/src/lib.rs Adds generated verifier contract implementation with embedded VK bytes.
groth16_verifier_gen/contracts/verifier/Cargo.toml Adds contract crate manifest for the generated verifier.
groth16_verifier_gen/contracts/gnark_verifier/src/test.rs Adds tests that load Gnark proof JSON and call the contract verifier.
groth16_verifier_gen/contracts/gnark_verifier/src/lib.rs Adds generated verifier contract implementation for Gnark VK bytes.
groth16_verifier_gen/contracts/gnark_verifier/Cargo.toml Adds contract crate manifest for the generated Gnark verifier.
groth16_verifier_gen/README.md Documents how to run the verifier generator on the included fixtures.
groth16_verifier_gen/Cargo.toml Adds workspace definition for the generated example contracts.
groth16_verifier_gen/Cargo.lock Adds lockfile for the new workspace.
groth16_verifier_gen/.gitignore Adds ignore rules for build artifacts and local Soroban config.
account/Cargo.lock Updates lockfile dependencies (appears unrelated to this PR’s stated scope).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread groth16_verifier/contracts/circom_verifier/src/test.rs Outdated
Comment thread groth16_verifier_gen/Cargo.toml Outdated
Comment thread groth16_verifier/contracts/bls12_381_verifier/Cargo.toml
Comment thread groth16_verifier/contracts/bn254_verifier/Cargo.toml
Comment thread groth16_verifier_gen/contracts/gnark_verifier/src/test.rs Outdated
@jayz22

jayz22 commented Jan 28, 2026

Copy link
Copy Markdown
Contributor

I don't think this should be its own example..
IIUC It's essentially the same code as https://github.com/stellar/soroban-examples/tree/main/groth16_verifier, with different hardcoded vk parameters generated from other systems.

The groth16 example was generated with circom/snarkjs with parameters included, if you feel strongly it should also have Gnark support, perhaps open a PR in the same example with another set of data?

The project you mentioned in the description is a code generator, which clearly isn't this example here.

@mysteryon88

Copy link
Copy Markdown
Author

@jayz22

Thanks for the feedback, that’s fair.

I think part of the reason I made it a separate example is that I felt a bit uncomfortable modifying or reusing an existing example, so I created a new one instead. I understand your point though, and I’ll update the PR soon to extend the existing Groth16 example rather than adding a new one.

It was also important for me to share a small utility I wrote for generating the contract / VK bindings, to avoid manual translation. Similar generators exist in other ecosystems, but I haven’t seen one for Stellar/Soroban yet.

I’ll rework the PR accordingly.

@jayz22

jayz22 commented Jan 28, 2026

Copy link
Copy Markdown
Contributor

@jayz22

Thanks for the feedback, that’s fair.

I think part of the reason I made it a separate example is that I felt a bit uncomfortable modifying or reusing an existing example, so I created a new one instead. I understand your point though, and I’ll update the PR soon to extend the existing Groth16 example rather than adding a new one.

It was also important for me to share a small utility I wrote for generating the contract / VK bindings, to avoid manual translation. Similar generators exist in other ecosystems, but I haven’t seen one for Stellar/Soroban yet.

I’ll rework the PR accordingly.

@mysteryon88 no worries! didn't mean to dismiss the work, this is a nice contribution improving its usability.
Please give it a try, happy to help you if needed!

@mysteryon88

Copy link
Copy Markdown
Author

@jayz22

Hi, I’ve updated the repository - I’d be glad to get your feedback!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 43 out of 56 changed files in this pull request and generated 9 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread groth16_verifier/.gitignore Outdated
Comment thread groth16_verifier/contracts/gnark_verifier/src/test.rs Outdated
Comment thread groth16_verifier/contracts/circom_verifier/src/test.rs Outdated
Comment thread groth16_verifier/data/arkworks/auxiliary/tests/integration_tests.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 52 out of 66 changed files in this pull request and generated 3 comments.

Comment thread README.md Outdated
@mysteryon88

Copy link
Copy Markdown
Author

@jayz22, hi! Is there any chance that my PR will be accepted?

@jayz22

jayz22 commented May 13, 2026

Copy link
Copy Markdown
Contributor

@jayz22, hi! Is there any chance that my PR will be accepted?

@mysteryon88 sorry for the late response.
This PR is still quite far off structurally. The two main values of this PR (as I understand it) 1. separate verification key bytes generated from separate tooling (with examples) 2. adding bn254 verifier.
So I suggest the following:

  • Make two groth16 contracts, one for each curve
  • Each contract should accept a verification key as input, or a set_verification_key method (with auth required).
  • Under tests/ for each contract, make each tooling generated data a separate instance.
    So roughly the following directory structure:
  groth16_verifier/
  ├── Cargo.toml              # workspace
  ├── Makefile                # iterates over contracts/
  ├── README.md
  └── contracts/
      ├── bls12_381_verifier/
      │   ├── Cargo.toml
      │   ├── Makefile
      │   ├── src/lib.rs
      │   └── tests/
      │       ├── circom.rs           # integration test
      │       ├── gnark.rs
      │       ├── arkworks.rs
      │       ├── common/mod.rs       # shared JSON parsers
      │       └── data/
      │           ├── circom/
      │           │   ├── README.md
      │           │   ├── verification_key.json
      │           │   ├── proof.json
      │           │   ├── public.json
      │           │   └── auxiliary/   # circom + snarkjs scripts
      │           ├── gnark/...
      │           └── arkworks/...
      └── bn254_verifier/
          ├── Cargo.toml
          ├── Makefile
          ├── src/lib.rs
          └── tests/
              ├── gnark.rs
              ├── common/mod.rs
              └── data/gnark/...

let me know if this makes sense.
(if it's and okay with you, I'm happy to tag a commit to your branch so that we can get this through the finish line sooner.)

@mysteryon88

Copy link
Copy Markdown
Author

@jayz22 thanks, this makes sense.

I’ll start restructuring the PR and should have the main changes pushed in the next couple of hours. After that, feel free to commit directly to my branch if you want to adjust or finish anything.

@mysteryon88 mysteryon88 changed the title add Soroban Groth16 verifier generator Add BN254 and BLS12-381 Groth16 verifier (Circom, Gnark, and Arkworks) May 13, 2026
@mysteryon88

Copy link
Copy Markdown
Author

@jayz22 hi, I’ve done it. Could you take a look and make any edits if needed? I think it turned out pretty well.

@mysteryon88

Copy link
Copy Markdown
Author

Hi @jayz22, just a quick ping on this. Could you take a look when you have a chance?

mysteryon88 and others added 2 commits August 5, 2026 23:18
- validate public inputs before field conversion
- reject x + r and other values outside the scalar field
- update Rust and Go dependencies
- regenerate proofs and verification keys
- add modulo vulnerability regression tests
@mysteryon88

Copy link
Copy Markdown
Author

@jayz22, I’d like to flag a security vulnerability in the current Groth16 verifier input pattern that makes this PR more time-sensitive.

While testing the verifier input boundary, I found that non-canonical public inputs can be reduced modulo the scalar-field order during conversion to Fr. As a result, two distinct raw 32-byte values, x and x + r, can be interpreted as the same field element and accepted with the same proof.

This does not break Groth16 soundness by itself. The vulnerability becomes exploitable when an application stores or compares the raw value, such as a nullifier or authorization identifier, while the verifier checks only its reduced field representation.

I prepared reproducible PoCs for both BN254 and BLS12-381, including a Privacy Pools example where the same proof can be reused for a second withdrawal by submitting n + r:

https://github.com/zk-examples/soroban-modulo-poc

I have already fixed the issue in my branch by accepting raw 32-byte public inputs, enforcing value < r before converting them to Fr, and adding regression tests for both curves.

The current example in main still exposes the unsafe input pattern, so users may copy it into real contracts. Could we please prioritize reviewing and merging this PR?

If the full PR is too large to merge quickly, I can immediately split the canonical-input validation and regression tests into a small security-only PR so the vulnerable pattern can be fixed first.

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.

3 participants