From fe3f84ac35319f2e7eff609aa9fbcbad7b6b4d3a Mon Sep 17 00:00:00 2001 From: arnaucube Date: Mon, 14 Oct 2024 12:37:17 +0200 Subject: [PATCH] Move the experimental frontends into a separate crate, so that when not using them they don't take several minutes to compile (and indirect dependencies). This saves several minutes (and MBs of data) on compilation time both when running tests in this repo, but also when using the sonobe lib as a dependency in external repos. --- .github/scripts/wasm-target-test-build.sh | 5 +- .github/workflows/ci.yml | 21 ++++--- .gitignore | 6 +- Cargo.toml | 3 +- README.md | 57 +++++++------------ examples/circom_full_flow.rs | 9 ++- examples/noir_full_flow.rs | 8 +-- examples/noname_full_flow.rs | 3 +- folding-schemes/Cargo.toml | 16 ++---- folding-schemes/src/folding/nova/zk.rs | 6 +- .../frontend/circom/test_folder/compile.sh | 4 -- folding-schemes/src/frontend/mod.rs | 3 - folding-schemes/src/frontend/utils.rs | 2 - frontends/Cargo.toml | 33 +++++++++++ frontends/README.md | 14 +++++ .../frontend => frontends/src}/circom/mod.rs | 42 +++++++------- .../test_folder/circuits/is_zero.circom | 0 frontends/src/circom/test_folder/compile.sh | 4 ++ .../circom/test_folder/cubic_circuit.circom | 0 .../test_folder/no_external_inputs.circom | 0 .../test_folder/with_external_inputs.circom | 0 .../src}/circom/utils.rs | 13 ++--- frontends/src/lib.rs | 3 + .../frontend => frontends/src}/noir/mod.rs | 19 +++---- .../src}/noir/test_folder/compile.sh | 2 +- .../noir/test_folder/test_circuit/Nargo.toml | 0 .../noir/test_folder/test_circuit/src/main.nr | 0 .../noir/test_folder/test_mimc/Nargo.toml | 0 .../noir/test_folder/test_mimc/src/main.nr | 0 .../test_no_external_inputs/Nargo.toml | 0 .../test_no_external_inputs/src/main.nr | 0 .../frontend => frontends/src}/noname/mod.rs | 9 ++- .../src}/noname/utils.rs | 0 solidity-verifiers/Cargo.toml | 1 + 34 files changed, 152 insertions(+), 131 deletions(-) delete mode 100755 folding-schemes/src/frontend/circom/test_folder/compile.sh create mode 100644 frontends/Cargo.toml create mode 100644 frontends/README.md rename {folding-schemes/src/frontend => frontends/src}/circom/mod.rs (89%) rename {folding-schemes/src/frontend => frontends/src}/circom/test_folder/circuits/is_zero.circom (100%) create mode 100755 frontends/src/circom/test_folder/compile.sh rename {folding-schemes/src/frontend => frontends/src}/circom/test_folder/cubic_circuit.circom (100%) rename {folding-schemes/src/frontend => frontends/src}/circom/test_folder/no_external_inputs.circom (100%) rename {folding-schemes/src/frontend => frontends/src}/circom/test_folder/with_external_inputs.circom (100%) rename {folding-schemes/src/frontend => frontends/src}/circom/utils.rs (92%) create mode 100644 frontends/src/lib.rs rename {folding-schemes/src/frontend => frontends/src}/noir/mod.rs (94%) rename {folding-schemes/src/frontend => frontends/src}/noir/test_folder/compile.sh (72%) rename {folding-schemes/src/frontend => frontends/src}/noir/test_folder/test_circuit/Nargo.toml (100%) rename {folding-schemes/src/frontend => frontends/src}/noir/test_folder/test_circuit/src/main.nr (100%) rename {folding-schemes/src/frontend => frontends/src}/noir/test_folder/test_mimc/Nargo.toml (100%) rename {folding-schemes/src/frontend => frontends/src}/noir/test_folder/test_mimc/src/main.nr (100%) rename {folding-schemes/src/frontend => frontends/src}/noir/test_folder/test_no_external_inputs/Nargo.toml (100%) rename {folding-schemes/src/frontend => frontends/src}/noir/test_folder/test_no_external_inputs/src/main.nr (100%) rename {folding-schemes/src/frontend => frontends/src}/noname/mod.rs (97%) rename {folding-schemes/src/frontend => frontends/src}/noname/utils.rs (100%) diff --git a/.github/scripts/wasm-target-test-build.sh b/.github/scripts/wasm-target-test-build.sh index e86ef832..64b9ba0a 100644 --- a/.github/scripts/wasm-target-test-build.sh +++ b/.github/scripts/wasm-target-test-build.sh @@ -15,7 +15,8 @@ cp "${GIT_ROOT}/rust-toolchain" . rustup target add wasm32-unknown-unknown wasm32-wasi # add dependencies -cargo add --path "${GIT_ROOT}/folding-schemes" --features wasm, parallel +cargo add --path "${GIT_ROOT}/frontends" --features wasm, parallel +cargo add --path "${GIT_ROOT}/folding-schemes" --features parallel cargo add getrandom --features js --target wasm32-unknown-unknown # test build for wasm32-* targets @@ -26,4 +27,4 @@ cargo build --release --target wasm32-wasi # delete test project cd ../ -rm -rf foobar \ No newline at end of file +rm -rf foobar diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b7ef464e..0319acd9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,9 +61,9 @@ jobs: curl -sSfL https://github.com/ethereum/solidity/releases/download/v0.8.4/solc-static-linux -o /usr/local/bin/solc chmod +x /usr/local/bin/solc - name: Execute compile.sh to generate .r1cs and .wasm from .circom - run: ./folding-schemes/src/frontend/circom/test_folder/compile.sh + run: ./frontends/src/circom/test_folder/compile.sh - name: Execute compile.sh to generate .json from noir - run: ./folding-schemes/src/frontend/noir/test_folder/compile.sh + run: ./frontends/src/noir/test_folder/compile.sh - name: Run tests uses: actions-rs/cargo@v1 with: @@ -95,11 +95,16 @@ jobs: default: true - name: Add target run: rustup target add ${{ matrix.target }} - - name: Wasm-compat build + - name: Wasm-compat frontends build uses: actions-rs/cargo@v1 with: command: build - args: -p folding-schemes --no-default-features --target ${{ matrix.target }} --features "wasm, parallel" + args: -p frontends --no-default-features --target ${{ matrix.target }} --features "wasm, parallel" + - name: Wasm-compat folding-schemes build + uses: actions-rs/cargo@v1 + with: + command: build + args: -p folding-schemes --no-default-features --target ${{ matrix.target }} --features "default,light-test" - name: Run wasm-compat script run: | chmod +x .github/scripts/wasm-target-test-build.sh @@ -127,9 +132,9 @@ jobs: curl -sSfL https://github.com/ethereum/solidity/releases/download/v0.8.4/solc-static-linux -o /usr/local/bin/solc chmod +x /usr/local/bin/solc - name: Execute compile.sh to generate .r1cs and .wasm from .circom - run: ./folding-schemes/src/frontend/circom/test_folder/compile.sh + run: ./frontends/src/circom/test_folder/compile.sh - name: Execute compile.sh to generate .json from noir - run: ./folding-schemes/src/frontend/noir/test_folder/compile.sh + run: ./frontends/src/noir/test_folder/compile.sh - name: Run examples tests run: cargo test --examples - name: Run examples @@ -160,9 +165,9 @@ jobs: include: - feature_set: basic features: --features default,light-test - # We only want to test `folding-schemes` package with `wasm` feature. + # We only want to test `frontends` package with `wasm` feature. - feature_set: wasm - features: -p folding-schemes --features wasm,parallel --target wasm32-unknown-unknown + features: -p frontends --features wasm,parallel --target wasm32-unknown-unknown steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 diff --git a/.gitignore b/.gitignore index d3067b1d..e2e3afdc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,14 @@ Cargo.lock # Circom generated files -folding-schemes/src/frontend/circom/test_folder/*_js/ +frontends/src/circom/test_folder/*_js/ *.r1cs *.sym # Noir generated files -folding-schemes/src/frontend/noir/test_folder/*/target/* +frontends/src/noir/test_folder/*/target/* -# generated contracts at test time +# generated contracts data solidity-verifiers/generated examples/*.sol examples/*.calldata diff --git a/Cargo.toml b/Cargo.toml index 8445a188..ab6063d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,8 @@ members = [ "folding-schemes", "solidity-verifiers", - "cli" + "cli", + "frontends" ] resolver = "2" diff --git a/README.md b/README.md index 5b742968..b416fef3 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ Sonobe is conceived as an exploratory effort with the aim to push forward the pr
> **Warning**: experimental code, do not use in production.
-> The code has not been audited. Several optimizations are also pending. Our focus so far has been on implementing the Nova and CycleFold schemes and achieving onchain (EVM) verification. +> The code has not been audited. Several optimizations are also pending. Our focus so far has been on implementing the Nova, HyperNova and ProtoGalaxy schemes, all with the CycleFold approach; and achieving the onchain (in EVM) verification of the folding proofs. + ## Schemes implemented @@ -27,52 +28,36 @@ Work in progress: - [ProtoGalaxy: Efficient ProtoStar-style folding of multiple instances](https://eprint.iacr.org/2023/1106.pdf), Liam Eagen, Ariel Gabizon. 2023 -## Available frontends - -Available frontends to define the folded circuit: - -- [arkworks](https://github.com/arkworks-rs), arkworks contributors -- [Circom](https://github.com/iden3/circom), iden3, 0Kims Association -- [Noname](https://github.com/zksecurity/noname), zkSecurity - -## Usage - -### Build & test -You can test the library for both, WASM-targets and regular ones. -#### Regular targets -Tier-S targets allow the user to simply run `cargo test` or `cargo build` without needing to worry about anything. -**We strongly recommend to test using the `light-test` feature.** Which will omit the computationally intensive parts of the tests such as -generating a SNARK of 4~5M constraints to then verify it. -#### WASM targets -In order to build the lib for WASM-targets, use the following command: -`cargo build -p folding-schemes --no-default-features --target wasm32-unknown-unknown --features "wasm, parallel"`. -Where the target can be any WASM one and the `parallel` feature is optional. +## Frontends -**Trying to build for a WASM-target without the `wasm` feature or viceversa will end up in a compilation error.** +Frontends allow to define the circuit to be folded (ie. `FCircuit`). +The recommended frontend is directly implementing the [`FCircuit` trait](https://github.com/privacy-scaling-explorations/sonobe/blob/main/folding-schemes/src/frontend/mod.rs#L16) with the Arkworks constraint system. -### Docs +Alternatively, experimental frontends for Circom, Noir and Noname can be found at [sonobe/frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/frontends), which have some computational (and time) overhead. -Detailed usage and design documentation can be found at [Sonobe docs](https://privacy-scaling-explorations.github.io/sonobe-docs/). +More details about the frontend interface and the experimental frontends can be found at the [sonobe-docs/frontend](https://privacy-scaling-explorations.github.io/sonobe-docs/usage/frontend.html) page. -### WASM-compatibility & features -The `sonobe/folding-schemes` crate is the only workspace member that supports WASM-target compilation. But, to have it working, `getrandom/js` needs -to be imported in the `Cargo.toml` of the crate that uses it as dependency. +## Usage +Import the library: ```toml [dependencies] -folding-schemes = { version = "0.1.0", default-features = false, features = ["parallel", "wasm"] } -getrandom = { version = "0.2", features = ["js"] } +folding-schemes = { git = "https://github.com/privacy-scaling-explorations/sonobe", package = "folding-schemes"} +solidity-verifiers = { git = "https://github.com/privacy-scaling-explorations/sonobe", package = "solidity-verifiers"} ``` -See more details about `getrandom` here: https://docs.rs/getrandom/latest/getrandom/#webassembly-support. -Also, notice that: -- `wasm` feature **IS MANDATORY** if compilation to WASM targets is desired. -- `parallel` feature enables some parallelization optimizations available in the crate. -- `light-test` feature runs the computationally-intensive parts of the testing such as the full proof generation for the Eth-decider circuit -of Nova which is approximately 4-5M constraints. **This feature only matters when it comes to running Sonobe's tests.** +Available features: +- `parallel` enables some parallelization optimizations available in the crate. It is enabled by default. +- `light-test` disables part of the DeciderEthCircuit various circuits (which accounts for ~9M constraints) so that the tests involving those circuits can run quickier. Do not use it outside tests. This feature is disabled by default. + +For WASM (in browser usage), details can be found at [sonobe-docs/usage/wasm](https://privacy-scaling-explorations.github.io/sonobe-docs/usage/wasm.html) + + +### Docs +Details on usage of the library, together with design documentation, can be found at the [Sonobe docs](https://privacy-scaling-explorations.github.io/sonobe-docs/). -### Folding Schemes introduction +## Folding Schemes introduction Folding schemes efficiently achieve incrementally verifiable computation (IVC), where the prover recursively proves the correct execution of the incremental computations. Once the IVC iterations are completed, the IVC proof is compressed into the Decider proof, a zkSNARK proof which proves that applying $n$ times the $F$ function (the circuit being folded) to the initial state ($z_0$) results in the final state ($z_n$). diff --git a/examples/circom_full_flow.rs b/examples/circom_full_flow.rs index dccf0d8e..66eefe02 100644 --- a/examples/circom_full_flow.rs +++ b/examples/circom_full_flow.rs @@ -23,10 +23,11 @@ use folding_schemes::{ decider_eth::{prepare_calldata, Decider as DeciderEth}, Nova, PreprocessorParam, }, - frontend::{circom::CircomFCircuit, FCircuit}, + frontend::FCircuit, transcript::poseidon::poseidon_canonical_config, Decider, FoldingScheme, }; +use frontends::circom::CircomFCircuit; use solidity_verifiers::{ evm::{compile_solidity, Evm}, utils::get_function_selector_for_nova_cyclefold_verifier, @@ -54,11 +55,9 @@ fn main() { ]; // initialize the Circom circuit - let r1cs_path = PathBuf::from( - "./folding-schemes/src/frontend/circom/test_folder/with_external_inputs.r1cs", - ); + let r1cs_path = PathBuf::from("./frontends/src/circom/test_folder/with_external_inputs.r1cs"); let wasm_path = PathBuf::from( - "./folding-schemes/src/frontend/circom/test_folder/with_external_inputs_js/with_external_inputs.wasm", + "./frontends/src/circom/test_folder/with_external_inputs_js/with_external_inputs.wasm", ); let f_circuit_params = (r1cs_path.into(), wasm_path.into(), 1, 2); diff --git a/examples/noir_full_flow.rs b/examples/noir_full_flow.rs index 64531098..9d153be8 100644 --- a/examples/noir_full_flow.rs +++ b/examples/noir_full_flow.rs @@ -20,13 +20,11 @@ use folding_schemes::{ decider_eth::{prepare_calldata, Decider as DeciderEth}, Nova, PreprocessorParam, }, - frontend::{ - noir::{load_noir_circuit, NoirFCircuit}, - FCircuit, - }, + frontend::FCircuit, transcript::poseidon::poseidon_canonical_config, Decider, FoldingScheme, }; +use frontends::noir::{load_noir_circuit, NoirFCircuit}; use std::{env, time::Instant}; use solidity_verifiers::{ @@ -44,7 +42,7 @@ fn main() { let cur_path = env::current_dir().unwrap(); let circuit_path = format!( - "{}/folding-schemes/src/frontend/noir/test_folder/test_mimc/target/test_mimc.json", + "{}/frontends/src/noir/test_folder/test_mimc/target/test_mimc.json", cur_path.to_str().unwrap() ); diff --git a/examples/noname_full_flow.rs b/examples/noname_full_flow.rs index 00dccbfb..6831a2e5 100644 --- a/examples/noname_full_flow.rs +++ b/examples/noname_full_flow.rs @@ -21,10 +21,11 @@ use folding_schemes::{ decider_eth::{prepare_calldata, Decider as DeciderEth}, Nova, PreprocessorParam, }, - frontend::{noname::NonameFCircuit, FCircuit}, + frontend::FCircuit, transcript::poseidon::poseidon_canonical_config, Decider, FoldingScheme, }; +use frontends::noname::NonameFCircuit; use std::time::Instant; use solidity_verifiers::{ diff --git a/folding-schemes/Cargo.toml b/folding-schemes/Cargo.toml index d7c45482..22b074de 100644 --- a/folding-schemes/Cargo.toml +++ b/folding-schemes/Cargo.toml @@ -9,28 +9,20 @@ ark-ff = { version = "^0.4.0", default-features = false, features = ["parallel", ark-poly = { version = "^0.4.0", default-features = false, features = ["parallel"] } ark-std = { version = "^0.4.0", default-features = false, features = ["parallel"] } ark-crypto-primitives = { version = "^0.4.0", default-features = false, features = ["r1cs", "sponge", "crh", "parallel"] } -ark-grumpkin = { version = "0.4.0", default-features = false } ark-poly-commit = { version = "^0.4.0", default-features = false, features = ["parallel"] } ark-relations = { version = "^0.4.0", default-features = false } -# this is patched at the workspace level +# ark-r1cs-std is patched at the workspace level ark-r1cs-std = { version = "0.4.0", default-features = false, features = ["parallel"] } ark-snark = { version = "^0.4.0", default-features = false } ark-serialize = { version = "^0.4.0", default-features = false } -ark-circom = { git = "https://github.com/arnaucube/circom-compat", default-features = false } ark-groth16 = { version = "^0.4.0", default-features = false, features = ["parallel"]} ark-bn254 = { version = "^0.4.0", default-features = false } +ark-grumpkin = { version = "0.4.0", default-features = false } thiserror = "1.0" rayon = "1" num-bigint = "0.4" num-integer = "0.1" -color-eyre = "=0.6.2" sha3 = "0.10" -ark-noname = { git = "https://github.com/dmpierre/ark-noname", branch = "feat/sonobe-integration" } -noname = { git = "https://github.com/dmpierre/noname" } -serde_json = "1.0.85" # to (de)serialize JSON -serde = "1.0.203" -acvm = { git = "https://github.com/noir-lang/noir", rev="2b4853e", default-features = false } -noir_arkworks_backend = { package="arkworks_backend", git = "https://github.com/dmpierre/arkworks_backend", branch = "feat/sonobe-integration" } log = "0.4" # tmp import for espresso's sumcheck @@ -46,6 +38,7 @@ ark-grumpkin = {version="0.4.0", features=["r1cs"]} ark-mnt4-298 = {version="0.4.0", features=["r1cs"]} ark-mnt6-298 = {version="0.4.0", features=["r1cs"]} rand = "0.8.5" +num-bigint = {version = "0.4", features = ["rand"]} tracing = { version = "0.1", default-features = false, features = [ "attributes" ] } tracing-subscriber = { version = "0.2" } @@ -55,9 +48,8 @@ tracing-subscriber = { version = "0.2" } getrandom = { version = "0.2", features = ["js"] } [features] -default = ["ark-circom/default", "parallel"] +default = ["parallel"] parallel = [] -wasm = ["ark-circom/wasm"] light-test = [] diff --git a/folding-schemes/src/folding/nova/zk.rs b/folding-schemes/src/folding/nova/zk.rs index 33f30cde..cdfbc1c4 100644 --- a/folding-schemes/src/folding/nova/zk.rs +++ b/folding-schemes/src/folding/nova/zk.rs @@ -15,13 +15,13 @@ /// final proof generation to a server. /// * Use-case-2: at the end of all the IVC folding steps (after n iterations of nova.prove_step), /// to 'blind' the IVC proof so then it can be sent to a server that will generate the final -/// decider snark proof. +/// decider SNARK proof. /// --> In this one, the user could externalize the Decider final proof generation to a /// server. /// * Use-case-3: the user does not care about the Decider (final compressed SNARK proof), and /// wants to generate a zk-proof of the IVC state to an IVC verifier (without any SNARK proof -/// involved). Note that this proof will be much bigger and expensive to verify than a Decider -/// SNARK proof. +/// involved). In this use-case, the zk is only added at the last IVCProof. Note that this proof +/// will be much bigger and expensive to verify than a Decider SNARK proof. /// /// The current implementation covers the Use-case-3. /// Use-case-1 can be achieved directly by a simpler version of the zk IVC scheme skipping steps diff --git a/folding-schemes/src/frontend/circom/test_folder/compile.sh b/folding-schemes/src/frontend/circom/test_folder/compile.sh deleted file mode 100755 index 6eae30ed..00000000 --- a/folding-schemes/src/frontend/circom/test_folder/compile.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -circom ./folding-schemes/src/frontend/circom/test_folder/cubic_circuit.circom --r1cs --sym --wasm --prime bn128 --output ./folding-schemes/src/frontend/circom/test_folder/ -circom ./folding-schemes/src/frontend/circom/test_folder/with_external_inputs.circom --r1cs --sym --wasm --prime bn128 --output ./folding-schemes/src/frontend/circom/test_folder/ -circom ./folding-schemes/src/frontend/circom/test_folder/no_external_inputs.circom --r1cs --sym --wasm --prime bn128 --output ./folding-schemes/src/frontend/circom/test_folder/ diff --git a/folding-schemes/src/frontend/mod.rs b/folding-schemes/src/frontend/mod.rs index 7cf9e432..8570c818 100644 --- a/folding-schemes/src/frontend/mod.rs +++ b/folding-schemes/src/frontend/mod.rs @@ -4,9 +4,6 @@ use ark_r1cs_std::fields::fp::FpVar; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; use ark_std::fmt::Debug; -pub mod circom; -pub mod noir; -pub mod noname; pub mod utils; /// FCircuit defines the trait of the circuit of the F function, which is the one being folded (ie. diff --git a/folding-schemes/src/frontend/utils.rs b/folding-schemes/src/frontend/utils.rs index 64d8847c..27d4ec98 100644 --- a/folding-schemes/src/frontend/utils.rs +++ b/folding-schemes/src/frontend/utils.rs @@ -152,14 +152,12 @@ impl FCircuit for CustomFCircuit { /// than the one done in the `AugmentedFCircuit`, but without adding all the extra constraints /// of the AugmentedF circuit logic, in order to run lighter tests when we're not interested in /// the the AugmentedF logic but in the wrapping of the circuits. -#[cfg(test)] pub struct WrapperCircuit> { pub FC: FC, // F circuit pub z_i: Option>, pub z_i1: Option>, } -#[cfg(test)] impl ark_relations::r1cs::ConstraintSynthesizer for WrapperCircuit where F: PrimeField, diff --git a/frontends/Cargo.toml b/frontends/Cargo.toml new file mode 100644 index 00000000..dec4be2f --- /dev/null +++ b/frontends/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "frontends" +version = "0.1.0" +edition = "2021" + +[dependencies] +ark-ff = { version = "^0.4.0", default-features = false, features = ["parallel", "asm"] } +ark-std = { version = "^0.4.0", default-features = false, features = ["parallel"] } +ark-relations = { version = "^0.4.0", default-features = false } +# ark-r1cs-std is patched at the workspace level +ark-r1cs-std = { version = "0.4.0", default-features = false, features = ["parallel"] } +ark-serialize = { version = "^0.4.0", default-features = false } +ark-circom = { git = "https://github.com/arnaucube/circom-compat", default-features = false } +num-bigint = "0.4" +ark-noname = { git = "https://github.com/dmpierre/ark-noname", branch = "feat/sonobe-integration" } +noname = { git = "https://github.com/dmpierre/noname" } +serde_json = "1.0.85" # to (de)serialize JSON +acvm = { git = "https://github.com/noir-lang/noir", rev="2b4853e", default-features = false } +noir_arkworks_backend = { package="arkworks_backend", git = "https://github.com/dmpierre/arkworks_backend", branch = "feat/sonobe-integration" } +folding-schemes = { path = "../folding-schemes/"} + +[dev-dependencies] +ark-bn254 = {version="0.4.0", features=["r1cs"]} + +# This allows the crate to be built when targeting WASM. +# See more at: https://docs.rs/getrandom/#webassembly-support +[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies] +getrandom = { version = "0.2", features = ["js"] } + +[features] +default = ["ark-circom/default", "parallel"] +parallel = [] +wasm = ["ark-circom/wasm"] diff --git a/frontends/README.md b/frontends/README.md new file mode 100644 index 00000000..a5161183 --- /dev/null +++ b/frontends/README.md @@ -0,0 +1,14 @@ +# frontends + +This crate contains *experimental frontends* for Sonobe. +The recommended frontend is to directly use [arkworks](https://github.com/arkworks-rs) to define the FCircuit, just following the [`FCircuit` trait](https://github.com/privacy-scaling-explorations/sonobe/blob/main/folding-schemes/src/frontend/mod.rs). + +## Experimental frontends +> Warning: the following frontends are experimental and some computational and time overhead is expected when using them compared to directly using the [arkworks frontend](https://github.com/privacy-scaling-explorations/sonobe/blob/main/folding-schemes/src/frontend/mod.rs). + +- [Circom](https://github.com/iden3/circom), iden3, 0Kims Association. Supported version`<=v2.1.9`. +- [Noir](https://github.com/noir-lang/noir), Aztec. +- [Noname](https://github.com/zksecurity/noname), zkSecurity. Partially supported. + + +Documentation about frontend interface and experimental frontends: https://privacy-scaling-explorations.github.io/sonobe-docs/usage/frontend.html diff --git a/folding-schemes/src/frontend/circom/mod.rs b/frontends/src/circom/mod.rs similarity index 89% rename from folding-schemes/src/frontend/circom/mod.rs rename to frontends/src/circom/mod.rs index a261f722..88a9da5b 100644 --- a/folding-schemes/src/frontend/circom/mod.rs +++ b/frontends/src/circom/mod.rs @@ -1,14 +1,12 @@ -use crate::frontend::FCircuit; -use crate::frontend::FpVar::Var; -use crate::utils::PathOrBin; -use crate::Error; use ark_circom::circom::{CircomCircuit, R1CS as CircomR1CS}; use ark_ff::PrimeField; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::fields::fp::FpVar; +use ark_r1cs_std::fields::fp::FpVar::Var; use ark_r1cs_std::R1CSVar; use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; use ark_std::fmt::Debug; +use folding_schemes::{frontend::FCircuit, utils::PathOrBin, Error}; use num_bigint::BigInt; use std::rc::Rc; use std::{fmt, usize}; @@ -187,10 +185,10 @@ impl FCircuit for CircomFCircuit { } impl CircomFCircuit { - fn fpvars_to_bigints(&self, fpVars: &[FpVar]) -> Result, SynthesisError> { + fn fpvars_to_bigints(&self, fpvars: &[FpVar]) -> Result, SynthesisError> { let mut input_values = Vec::new(); // converts each FpVar to PrimeField value, then to num_bigint::BigInt. - for fp_var in fpVars.iter() { + for fp_var in fpvars.iter() { // extracts the PrimeField value from FpVar. let primefield_value = fp_var.value()?; // converts the PrimeField value to num_bigint::BigInt. @@ -213,9 +211,9 @@ pub mod tests { // Tests the step_native function of CircomFCircuit. #[test] fn test_circom_step_native() { - let r1cs_path = PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit.r1cs"); + let r1cs_path = PathBuf::from("./src/circom/test_folder/cubic_circuit.r1cs"); let wasm_path = - PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); + PathBuf::from("./src/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); let circom_fcircuit = CircomFCircuit::::new((r1cs_path.into(), wasm_path.into(), 1, 0)).unwrap(); // state_len:1, external_inputs_len:0 @@ -228,9 +226,9 @@ pub mod tests { // Tests the generate_step_constraints function of CircomFCircuit. #[test] fn test_circom_step_constraints() { - let r1cs_path = PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit.r1cs"); + let r1cs_path = PathBuf::from("./src/circom/test_folder/cubic_circuit.r1cs"); let wasm_path = - PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); + PathBuf::from("./src/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); let circom_fcircuit = CircomFCircuit::::new((r1cs_path.into(), wasm_path.into(), 1, 0)).unwrap(); // state_len:1, external_inputs_len:0 @@ -249,16 +247,16 @@ pub mod tests { // Tests the WrapperCircuit with CircomFCircuit. #[test] fn test_wrapper_circomtofcircuit() { - let r1cs_path = PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit.r1cs"); + let r1cs_path = PathBuf::from("./src/circom/test_folder/cubic_circuit.r1cs"); let wasm_path = - PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); + PathBuf::from("./src/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); let circom_fcircuit = CircomFCircuit::::new((r1cs_path.into(), wasm_path.into(), 1, 0)).unwrap(); // state_len:1, external_inputs_len:0 // Allocates z_i1 by using step_native function. let z_i = vec![Fr::from(3_u32)]; - let wrapper_circuit = crate::frontend::utils::WrapperCircuit { + let wrapper_circuit = folding_schemes::frontend::utils::WrapperCircuit { FC: circom_fcircuit.clone(), z_i: Some(z_i.clone()), z_i1: Some(circom_fcircuit.step_native(0, z_i.clone(), vec![]).unwrap()), @@ -275,10 +273,9 @@ pub mod tests { #[test] fn test_circom_external_inputs() { - let r1cs_path = - PathBuf::from("./src/frontend/circom/test_folder/with_external_inputs.r1cs"); + let r1cs_path = PathBuf::from("./src/circom/test_folder/with_external_inputs.r1cs"); let wasm_path = PathBuf::from( - "./src/frontend/circom/test_folder/with_external_inputs_js/with_external_inputs.wasm", + "./src/circom/test_folder/with_external_inputs_js/with_external_inputs.wasm", ); let circom_fcircuit = CircomFCircuit::::new((r1cs_path.into(), wasm_path.into(), 1, 2)).unwrap(); // state_len:1, external_inputs_len:2 @@ -320,10 +317,9 @@ pub mod tests { #[test] fn test_circom_no_external_inputs() { - let r1cs_path = PathBuf::from("./src/frontend/circom/test_folder/no_external_inputs.r1cs"); - let wasm_path = PathBuf::from( - "./src/frontend/circom/test_folder/no_external_inputs_js/no_external_inputs.wasm", - ); + let r1cs_path = PathBuf::from("./src/circom/test_folder/no_external_inputs.r1cs"); + let wasm_path = + PathBuf::from("./src/circom/test_folder/no_external_inputs_js/no_external_inputs.wasm"); let circom_fcircuit = CircomFCircuit::::new((r1cs_path.into(), wasm_path.into(), 3, 0)).unwrap(); let cs = ConstraintSystem::::new_ref(); @@ -353,9 +349,9 @@ pub mod tests { #[test] fn test_custom_code() { - let r1cs_path = PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit.r1cs"); + let r1cs_path = PathBuf::from("./src/circom/test_folder/cubic_circuit.r1cs"); let wasm_path = - PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); + PathBuf::from("./src/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); let mut circom_fcircuit = CircomFCircuit::::new((r1cs_path.into(), wasm_path.into(), 1, 0)).unwrap(); // state_len:1, external_inputs_len:0 @@ -367,7 +363,7 @@ pub mod tests { // Allocates z_i1 by using step_native function. let z_i = vec![Fr::from(3_u32)]; - let wrapper_circuit = crate::frontend::utils::WrapperCircuit { + let wrapper_circuit = folding_schemes::frontend::utils::WrapperCircuit { FC: circom_fcircuit.clone(), z_i: Some(z_i.clone()), z_i1: Some(circom_fcircuit.step_native(0, z_i.clone(), vec![]).unwrap()), diff --git a/folding-schemes/src/frontend/circom/test_folder/circuits/is_zero.circom b/frontends/src/circom/test_folder/circuits/is_zero.circom similarity index 100% rename from folding-schemes/src/frontend/circom/test_folder/circuits/is_zero.circom rename to frontends/src/circom/test_folder/circuits/is_zero.circom diff --git a/frontends/src/circom/test_folder/compile.sh b/frontends/src/circom/test_folder/compile.sh new file mode 100755 index 00000000..736c06c1 --- /dev/null +++ b/frontends/src/circom/test_folder/compile.sh @@ -0,0 +1,4 @@ +#!/bin/bash +circom ./frontends/src/circom/test_folder/cubic_circuit.circom --r1cs --sym --wasm --prime bn128 --output ./frontends/src/circom/test_folder/ +circom ./frontends/src/circom/test_folder/with_external_inputs.circom --r1cs --sym --wasm --prime bn128 --output ./frontends/src/circom/test_folder/ +circom ./frontends/src/circom/test_folder/no_external_inputs.circom --r1cs --sym --wasm --prime bn128 --output ./frontends/src/circom/test_folder/ diff --git a/folding-schemes/src/frontend/circom/test_folder/cubic_circuit.circom b/frontends/src/circom/test_folder/cubic_circuit.circom similarity index 100% rename from folding-schemes/src/frontend/circom/test_folder/cubic_circuit.circom rename to frontends/src/circom/test_folder/cubic_circuit.circom diff --git a/folding-schemes/src/frontend/circom/test_folder/no_external_inputs.circom b/frontends/src/circom/test_folder/no_external_inputs.circom similarity index 100% rename from folding-schemes/src/frontend/circom/test_folder/no_external_inputs.circom rename to frontends/src/circom/test_folder/no_external_inputs.circom diff --git a/folding-schemes/src/frontend/circom/test_folder/with_external_inputs.circom b/frontends/src/circom/test_folder/with_external_inputs.circom similarity index 100% rename from folding-schemes/src/frontend/circom/test_folder/with_external_inputs.circom rename to frontends/src/circom/test_folder/with_external_inputs.circom diff --git a/folding-schemes/src/frontend/circom/utils.rs b/frontends/src/circom/utils.rs similarity index 92% rename from folding-schemes/src/frontend/circom/utils.rs rename to frontends/src/circom/utils.rs index f2c89199..dbe86050 100644 --- a/folding-schemes/src/frontend/circom/utils.rs +++ b/frontends/src/circom/utils.rs @@ -4,11 +4,10 @@ use ark_circom::{ }; use ark_ff::{BigInteger, PrimeField}; use ark_serialize::Read; -use color_eyre::Result; use num_bigint::{BigInt, Sign}; use std::{fs::File, io::Cursor, marker::PhantomData, path::PathBuf}; -use crate::{utils::PathOrBin, Error}; +use folding_schemes::{utils::PathOrBin, Error}; // A struct that wraps Circom functionalities, allowing for extraction of R1CS and witnesses // based on file paths to Circom's .r1cs and .wasm. @@ -134,14 +133,14 @@ mod tests { use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystem}; //To generate .r1cs and .wasm files, run the below command in the terminal. - //bash ./folding-schemes/src/frontend/circom/test_folder/compile.sh + //bash ./frontends/src/circom/test_folder/compile.sh // Test the satisfication by using the CircomBuilder of circom-compat #[test] fn test_circombuilder_satisfied() { let cfg = CircomConfig::::new( - "./src/frontend/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm", - "./src/frontend/circom/test_folder/cubic_circuit.r1cs", + "./src/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm", + "./src/circom/test_folder/cubic_circuit.r1cs", ) .unwrap(); let mut builder = CircomBuilder::new(cfg); @@ -156,9 +155,9 @@ mod tests { // Test the satisfication by using the CircomWrapper #[test] fn test_extract_r1cs_and_witness() { - let r1cs_path = PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit.r1cs"); + let r1cs_path = PathBuf::from("./src/circom/test_folder/cubic_circuit.r1cs"); let wasm_path = - PathBuf::from("./src/frontend/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); + PathBuf::from("./src/circom/test_folder/cubic_circuit_js/cubic_circuit.wasm"); let inputs = vec![("ivc_input".to_string(), vec![BigInt::from(3)])]; let wrapper = CircomWrapper::::new(r1cs_path.into(), wasm_path.into()).unwrap(); diff --git a/frontends/src/lib.rs b/frontends/src/lib.rs new file mode 100644 index 00000000..f6b56f35 --- /dev/null +++ b/frontends/src/lib.rs @@ -0,0 +1,3 @@ +pub mod circom; +pub mod noir; +pub mod noname; diff --git a/folding-schemes/src/frontend/noir/mod.rs b/frontends/src/noir/mod.rs similarity index 94% rename from folding-schemes/src/frontend/noir/mod.rs rename to frontends/src/noir/mod.rs index b0910910..22d95776 100644 --- a/folding-schemes/src/frontend/noir/mod.rs +++ b/frontends/src/noir/mod.rs @@ -1,8 +1,5 @@ use std::collections::HashMap; -use crate::{utils::PathOrBin, Error}; - -use super::FCircuit; use acvm::{ acir::{ acir_field::GenericFieldElement, @@ -16,6 +13,7 @@ use ark_ff::PrimeField; use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar}; use ark_relations::r1cs::ConstraintSynthesizer; use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError}; +use folding_schemes::{frontend::FCircuit, utils::PathOrBin, Error}; use noir_arkworks_backend::{ read_program_from_binary, read_program_from_file, sonobe_bridge::AcirCircuitSonobe, }; @@ -30,7 +28,7 @@ pub struct NoirFCircuit { impl FCircuit for NoirFCircuit { type Params = (PathOrBin, usize, usize); - fn new(params: Self::Params) -> Result { + fn new(params: Self::Params) -> Result { let (source, state_len, external_inputs_len) = params; let program = match source { PathOrBin::Path(path) => read_program_from_file(path), @@ -70,7 +68,7 @@ impl FCircuit for NoirFCircuit { _i: usize, z_i: Vec, external_inputs: Vec, // inputs that are not part of the state - ) -> Result, crate::Error> { + ) -> Result, Error> { let mut acvm = ACVM::new( &StubbedBlackBoxSolver, &self.circuit.opcodes, @@ -226,20 +224,21 @@ pub fn load_noir_circuit(path: String) -> Circuit::new_ref(); let cur_path = env::current_dir().unwrap(); let circuit_path = format!( - "{}/src/frontend/noir/test_folder/test_circuit/target/test_circuit.json", + "{}/src/noir/test_folder/test_circuit/target/test_circuit.json", cur_path.to_str().unwrap() ); let circuit = load_noir_circuit(circuit_path); @@ -283,7 +282,7 @@ mod tests { let cs = ConstraintSystem::::new_ref(); let cur_path = env::current_dir().unwrap(); let circuit_path = format!( - "{}/src/frontend/noir/test_folder/test_no_external_inputs/target/test_no_external_inputs.json", + "{}/src/noir/test_folder/test_no_external_inputs/target/test_no_external_inputs.json", cur_path.to_str().unwrap() ); let circuit = load_noir_circuit(circuit_path); diff --git a/folding-schemes/src/frontend/noir/test_folder/compile.sh b/frontends/src/noir/test_folder/compile.sh similarity index 72% rename from folding-schemes/src/frontend/noir/test_folder/compile.sh rename to frontends/src/noir/test_folder/compile.sh index 413d2a92..ea408eb4 100755 --- a/folding-schemes/src/frontend/noir/test_folder/compile.sh +++ b/frontends/src/noir/test_folder/compile.sh @@ -1,6 +1,6 @@ #!/bin/bash CUR_DIR=$(pwd) -TEST_PATH="${CUR_DIR}/folding-schemes/src/frontend/noir/test_folder/" +TEST_PATH="${CUR_DIR}/frontends/src/noir/test_folder/" for test_path in test_circuit test_mimc test_no_external_inputs; do FOLDER="${TEST_PATH}${test_path}/" cd ${FOLDER} && nargo compile && cd ${TEST_PATH} diff --git a/folding-schemes/src/frontend/noir/test_folder/test_circuit/Nargo.toml b/frontends/src/noir/test_folder/test_circuit/Nargo.toml similarity index 100% rename from folding-schemes/src/frontend/noir/test_folder/test_circuit/Nargo.toml rename to frontends/src/noir/test_folder/test_circuit/Nargo.toml diff --git a/folding-schemes/src/frontend/noir/test_folder/test_circuit/src/main.nr b/frontends/src/noir/test_folder/test_circuit/src/main.nr similarity index 100% rename from folding-schemes/src/frontend/noir/test_folder/test_circuit/src/main.nr rename to frontends/src/noir/test_folder/test_circuit/src/main.nr diff --git a/folding-schemes/src/frontend/noir/test_folder/test_mimc/Nargo.toml b/frontends/src/noir/test_folder/test_mimc/Nargo.toml similarity index 100% rename from folding-schemes/src/frontend/noir/test_folder/test_mimc/Nargo.toml rename to frontends/src/noir/test_folder/test_mimc/Nargo.toml diff --git a/folding-schemes/src/frontend/noir/test_folder/test_mimc/src/main.nr b/frontends/src/noir/test_folder/test_mimc/src/main.nr similarity index 100% rename from folding-schemes/src/frontend/noir/test_folder/test_mimc/src/main.nr rename to frontends/src/noir/test_folder/test_mimc/src/main.nr diff --git a/folding-schemes/src/frontend/noir/test_folder/test_no_external_inputs/Nargo.toml b/frontends/src/noir/test_folder/test_no_external_inputs/Nargo.toml similarity index 100% rename from folding-schemes/src/frontend/noir/test_folder/test_no_external_inputs/Nargo.toml rename to frontends/src/noir/test_folder/test_no_external_inputs/Nargo.toml diff --git a/folding-schemes/src/frontend/noir/test_folder/test_no_external_inputs/src/main.nr b/frontends/src/noir/test_folder/test_no_external_inputs/src/main.nr similarity index 100% rename from folding-schemes/src/frontend/noir/test_folder/test_no_external_inputs/src/main.nr rename to frontends/src/noir/test_folder/test_no_external_inputs/src/main.nr diff --git a/folding-schemes/src/frontend/noname/mod.rs b/frontends/src/noname/mod.rs similarity index 97% rename from folding-schemes/src/frontend/noname/mod.rs rename to frontends/src/noname/mod.rs index 61ac1e7a..0de41ebf 100644 --- a/folding-schemes/src/frontend/noname/mod.rs +++ b/frontends/src/noname/mod.rs @@ -1,4 +1,3 @@ -use crate::Error; use ark_noname::sonobe::NonameSonobeCircuit; use ark_r1cs_std::alloc::AllocVar; use ark_r1cs_std::fields::fp::FpVar; @@ -8,9 +7,9 @@ use std::marker::PhantomData; use self::utils::NonameInputs; -use super::FCircuit; use ark_ff::PrimeField; use ark_noname::utils::compile_source_code; +use folding_schemes::{frontend::FCircuit, Error}; use noname::backends::{r1cs::R1CS as R1CSNoname, BackendField}; use noname::witness::CompiledCircuit; pub mod utils; @@ -25,7 +24,7 @@ pub struct NonameFCircuit { impl FCircuit for NonameFCircuit { type Params = (String, usize, usize); - fn new(params: Self::Params) -> Result { + fn new(params: Self::Params) -> Result { let (code, state_len, external_inputs_len) = params; let compiled_circuit = compile_source_code::(&code).map_err(|_| { Error::Other("Encountered an error while compiling a noname circuit".to_owned()) @@ -51,7 +50,7 @@ impl FCircuit for NonameFCircuit { _i: usize, z_i: Vec, external_inputs: Vec, - ) -> Result, crate::Error> { + ) -> Result, Error> { let wtns_external_inputs = NonameInputs::from((&external_inputs, "external_inputs".to_string())); let wtns_ivc_inputs = NonameInputs::from((&z_i, "ivc_inputs".to_string())); @@ -119,7 +118,7 @@ mod tests { use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar, R1CSVar}; use noname::backends::r1cs::R1csBn254Field; - use crate::frontend::FCircuit; + use folding_schemes::frontend::FCircuit; use super::NonameFCircuit; use ark_relations::r1cs::ConstraintSystem; diff --git a/folding-schemes/src/frontend/noname/utils.rs b/frontends/src/noname/utils.rs similarity index 100% rename from folding-schemes/src/frontend/noname/utils.rs rename to frontends/src/noname/utils.rs diff --git a/solidity-verifiers/Cargo.toml b/solidity-verifiers/Cargo.toml index 907f93bf..e165016b 100644 --- a/solidity-verifiers/Cargo.toml +++ b/solidity-verifiers/Cargo.toml @@ -29,6 +29,7 @@ ark-bn254 = {version="0.4.0", features=["r1cs"]} ark-grumpkin = {version="0.4.0", features=["r1cs"]} rand = "0.8.5" folding-schemes = { path = "../folding-schemes/", features=["light-test"]} +frontends = { path = "../frontends/"} noname = { git = "https://github.com/dmpierre/noname" } [features]