Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/circom prover #304

Merged
merged 11 commits into from
Jan 25, 2025
Merged

Feat/circom prover #304

merged 11 commits into from
Jan 25, 2025

Conversation

KimiWu123
Copy link
Collaborator

close #299

Copy link

cloudflare-workers-and-pages bot commented Jan 22, 2025

Deploying mopro with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0201e3d
Status:⚡️  Build in progress...

View logs

@KimiWu123 KimiWu123 force-pushed the feat/circom-prover branch 3 times, most recently from f5ba880 to 82c6c52 Compare January 23, 2025 02:09
@KimiWu123 KimiWu123 marked this pull request as ready for review January 23, 2025 03:07
@KimiWu123 KimiWu123 requested a review from vivianjeng January 23, 2025 03:15
Copy link
Collaborator

@chancehudson chancehudson left a comment

Choose a reason for hiding this comment

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

Could i get a concrete rationale for creating a new package in the monorepo instead of breaking the ark logic into a separate file instead? This adds a layer of complexity and as such i'd expect concrete upside. As it stands i don't see the upside and am against adding a new package.


/// To create witness functions corresponding to different witness generation libs.
#[macro_export]
macro_rules! create_witness_fn {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this macro is a bad abstraction. Why do we want to hide which adapter is being used to create the witness function? e.g. why can't we use rust_witness and witnesscalc_adapter directly? Adding this adds a layer of complexity, what is the justification?

Copy link
Collaborator Author

@KimiWu123 KimiWu123 Jan 24, 2025

Choose a reason for hiding this comment

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

removed in 265abb6

inputs: HashMap<String, Vec<String>>,
dat_path: String,
) -> Vec<BigUint> {
std::thread::spawn(move || {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This thread is a noop. This generate_witness implementation creates a background thread, then blocks the main thread waiting for the background thread (e.g. immediately joins the thread below).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nice catch! I forgot to handle this. fixed in b6d39a6

@chancehudson
Copy link
Collaborator

ah i see, the intention is to publish the package on crates.io?

@KimiWu123
Copy link
Collaborator Author

KimiWu123 commented Jan 23, 2025

Could i get a concrete rationale for creating a new package in the monorepo instead of breaking the ark logic into a separate file instead? This adds a layer of complexity and as such i'd expect concrete upside. As it stands i don't see the upside and am against adding a new package.

I think Vivian's intention is

We can maintain our own circom-prover for cross-platform solution, and we can publish our packages.
In the future, we can encourage ZK applications (e.g. Semaphore) to use the crate circom-prover instead of circom-compat for cross-platform proving.

, want to address

We have several adapters (now or in the future). We need to easily switch between adapters

and also to simply the dependencies of mopro, here.

At the beginning, Vivian proposed to have a separated repo to address above issues. However, I suggested to put the logic inside mopro repo and have another crate. The reason why I suggest that is because it'll be getting harder and harder to maintain if we separate our code in so many different repos. And it's also hard for newcomers to get whole pictures of mopro.

I would love to hear your feedback on how to fix #299 and make the codebase clean! 😄 Moving to circom-prover repo works for me as well.

@vivianjeng
Copy link
Collaborator

@chancehudson Yes
to be clarified
It will be circom-prover (#299) in the future
(will be here https://github.com/zkmopro/circom-prover)
But for current stage, it would be convenient to put in monorepo like this

and I think the rapidsnark can also be in part of circom-prover
like we can set different features to enable different adapter
e.g. features = ["ark-works"] or features = ["rapidsnark"]
how do you think? related to this PR #305

and I think the rapidsnark-adpater can also be a crate like witnesscalc-adpater
I think they are quite independent to mopro or circom-prover

@KimiWu123 KimiWu123 force-pushed the feat/circom-prover branch 5 times, most recently from 524ec15 to b6d39a6 Compare January 24, 2025 05:11
Copy link
Collaborator

@vivianjeng vivianjeng left a comment

Choose a reason for hiding this comment

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

I think the more ideal implementation is to have like

witness/
   witnesscalc.rs
   rust_witness.rs
   mod.rs

and we enable each by

#[cfg(feature = "witnesscalc")]
mod witnesscalc;
#[cfg(feature = "rust-witness")]
mod rust_witness;

so we don't have to set many feature flags
and what if people set two different witness generators at the same time?
e.g. rustwitness and witnesscalc

it looks like it will execute the same operation twice?

            #[cfg(feature = "witnesscalc")]
            WitnessFn::WitnessCalc(wit_fn) => wit_fn(bigint_inputs, _dat_path.as_str()),
            #[cfg(feature = "rustwitness")]
            WitnessFn::RustWitness(wit_fn) => wit_fn(bigint_inputs),

I actually prefer the way if we can enable both features at the same time
(though it might not make sense)
but we need to design the functions
like generate_witness_rust_witness, generate_witness_witnesscalc
and init the prover like
let circom_prover = CircomProver(wtns_fn, proof_fn);

or we need to check if one feature is enabled, and another should not be executed

@KimiWu123
Copy link
Collaborator Author

KimiWu123 commented Jan 24, 2025

I think the more ideal implementation is to have like

witness/
   witnesscalc.rs
   rust_witness.rs
   mod.rs

and we enable each by

#[cfg(feature = "witnesscalc")]
mod witnesscalc;
#[cfg(feature = "rust-witness")]
mod rust_witness;

It's a good idea, but I realized there is no many code in witnesscalc.rs or rust_witness.rs. It seems a little over design for me and that's why I kept two different witness generation functions in the same file.

so we don't have to set many feature flags and what if people set two different witness generators at the same time? e.g. rustwitness and witnesscalc

it looks like it will execute the same operation twice?

            #[cfg(feature = "witnesscalc")]
            WitnessFn::WitnessCalc(wit_fn) => wit_fn(bigint_inputs, _dat_path.as_str()),
            #[cfg(feature = "rustwitness")]
            WitnessFn::RustWitness(wit_fn) => wit_fn(bigint_inputs),

No, it won't execute the same operation twice. wit_fn is passed from outside, it's the first argument of generate_witness. Callers can call which witness generation function as they want. For example, if both features were set, the code would be

             WitnessFn::WitnessCalc(wit_fn) => wit_fn(bigint_inputs, _dat_path.as_str()),
             WitnessFn::RustWitness(wit_fn) => wit_fn(bigint_inputs),

Just like a normal match case.

@KimiWu123
Copy link
Collaborator Author

KimiWu123 commented Jan 25, 2025

let circom_prover = CircomProver(wtns_fn, proof_fn);

I was considering this design as well, but it seems not really necessary to do in this way. I think current design is more lightweight, people can call any functions as they want, not have to init a CircomProver first. It better to support all the options for witness and proving in this kind of desgin, for example,

let a = CircomProver(rust_witness, arkworks);
let b = CircomProver(witness_calc, arkworks);

which means it better not to use cfg(feature) to control the output of CircomProver, supports all features at a time. Otherwise, it'll be strange that I can use rust_witness in this release/package but can't in another release. Not sure if it's clear enough.

The only benefit I can image is that we don't need to pass witness/witness_thread around, just a single prove can handle everything.

Copy link
Collaborator

@vivianjeng vivianjeng left a comment

Choose a reason for hiding this comment

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

LGTM
Just some lines can be removed

test-e2e/src/lib.rs Outdated Show resolved Hide resolved
circom-prover/src/lib.rs Outdated Show resolved Hide resolved
KimiWu123 and others added 2 commits January 25, 2025 15:50
@KimiWu123 KimiWu123 merged commit cc08bb5 into main Jan 25, 2025
25 of 26 checks passed
@KimiWu123 KimiWu123 mentioned this pull request Jan 25, 2025
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.

circom-prover spec
4 participants