Browse Source

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). (#168)

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.
main
arnaucube 2 months ago
committed by GitHub
parent
commit
234600b39f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
34 changed files with 161 additions and 130 deletions
  1. +3
    -2
      .github/scripts/wasm-target-test-build.sh
  2. +13
    -8
      .github/workflows/ci.yml
  3. +3
    -3
      .gitignore
  4. +2
    -1
      Cargo.toml
  5. +26
    -35
      README.md
  6. +4
    -5
      examples/circom_full_flow.rs
  7. +3
    -5
      examples/noir_full_flow.rs
  8. +2
    -1
      examples/noname_full_flow.rs
  9. +4
    -12
      folding-schemes/Cargo.toml
  10. +3
    -3
      folding-schemes/src/folding/nova/zk.rs
  11. +0
    -4
      folding-schemes/src/frontend/circom/test_folder/compile.sh
  12. +0
    -3
      folding-schemes/src/frontend/mod.rs
  13. +0
    -2
      folding-schemes/src/frontend/utils.rs
  14. +33
    -0
      frontends/Cargo.toml
  15. +18
    -0
      frontends/README.md
  16. +19
    -23
      frontends/src/circom/mod.rs
  17. +0
    -0
      frontends/src/circom/test_folder/circuits/is_zero.circom
  18. +4
    -0
      frontends/src/circom/test_folder/compile.sh
  19. +0
    -0
      frontends/src/circom/test_folder/cubic_circuit.circom
  20. +0
    -0
      frontends/src/circom/test_folder/no_external_inputs.circom
  21. +0
    -0
      frontends/src/circom/test_folder/with_external_inputs.circom
  22. +6
    -7
      frontends/src/circom/utils.rs
  23. +3
    -0
      frontends/src/lib.rs
  24. +9
    -10
      frontends/src/noir/mod.rs
  25. +1
    -1
      frontends/src/noir/test_folder/compile.sh
  26. +0
    -0
      frontends/src/noir/test_folder/test_circuit/Nargo.toml
  27. +0
    -0
      frontends/src/noir/test_folder/test_circuit/src/main.nr
  28. +0
    -0
      frontends/src/noir/test_folder/test_mimc/Nargo.toml
  29. +0
    -0
      frontends/src/noir/test_folder/test_mimc/src/main.nr
  30. +0
    -0
      frontends/src/noir/test_folder/test_no_external_inputs/Nargo.toml
  31. +0
    -0
      frontends/src/noir/test_folder/test_no_external_inputs/src/main.nr
  32. +4
    -5
      frontends/src/noname/mod.rs
  33. +0
    -0
      frontends/src/noname/utils.rs
  34. +1
    -0
      solidity-verifiers/Cargo.toml

+ 3
- 2
.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
rm -rf foobar

+ 13
- 8
.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

+ 3
- 3
.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

+ 2
- 1
Cargo.toml

@ -2,7 +2,8 @@
members = [
"folding-schemes",
"solidity-verifiers",
"cli"
"cli",
"frontends"
]
resolver = "2"

+ 26
- 35
README.md

@ -13,7 +13,8 @@ Sonobe is conceived as an exploratory effort with the aim to push forward the pr
<br>
> **Warning**: experimental code, do not use in production.<br>
> 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,42 @@ 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:
## Frontends
- [arkworks](https://github.com/arkworks-rs), arkworks contributors
- [Circom](https://github.com/iden3/circom), iden3, 0Kims Association
- [Noname](https://github.com/zksecurity/noname), zkSecurity
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.
## Usage
Alternatively, experimental frontends for [Circom](https://github.com/iden3/circom), [Noir](https://github.com/noir-lang/noir) and [Noname](https://github.com/zksecurity/noname) can be found at the [sonobe/frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/frontends) directory, which have some computational (and time) overhead.
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.
### 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.
## Usage
Import the library:
```toml
[dependencies]
folding-schemes = { git = "https://github.com/privacy-scaling-explorations/sonobe", package = "folding-schemes"}
```
**Trying to build for a WASM-target without the `wasm` feature or viceversa will end up in a compilation error.**
Available packages:
- `folding-schemes`: main crate, contains the different scheme implementations, together with commitment schemes, frontend trait, arithmetization, transcript, etc.
- `solidity-verifiers`: contains the templating logic to output the verifier contracts for the DeciderEth proofs. Currently only supports Nova+CycleFold DeciderEth proofs.
- `frontends`: contains the experimental frontends other than the arkworks frontend. More details at the [sonobe/frontends](https://github.com/privacy-scaling-explorations/sonobe/tree/main/frontends) directory.
### Docs
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 faster. Do not use it outside tests. This feature is disabled by default.
Detailed usage and design documentation can be found at [Sonobe docs](https://privacy-scaling-explorations.github.io/sonobe-docs/).
Examples of usage can be found at the [examples](https://github.com/privacy-scaling-explorations/sonobe/tree/main/examples) directory.
### WASM-compatibility & features
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).
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.
```toml
[dependencies]
folding-schemes = { version = "0.1.0", default-features = false, features = ["parallel", "wasm"] }
getrandom = { version = "0.2", features = ["js"] }
```
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.**
### 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$).

+ 4
- 5
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);

+ 3
- 5
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()
);

+ 2
- 1
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::{

+ 4
- 12
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 = []

+ 3
- 3
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

+ 0
- 4
folding-schemes/src/frontend/circom/test_folder/compile.sh

@ -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/

+ 0
- 3
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.

+ 0
- 2
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<F: PrimeField, FC: FCircuit<F>> {
pub FC: FC, // F circuit
pub z_i: Option<Vec<F>>,
pub z_i1: Option<Vec<F>>,
}
#[cfg(test)]
impl<F, FC> ark_relations::r1cs::ConstraintSynthesizer<F> for WrapperCircuit<F, FC>
where
F: PrimeField,

+ 33
- 0
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"]

+ 18
- 0
frontends/README.md

@ -0,0 +1,18 @@
# 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).
Available experimental frontends:
- [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
## Implementing new frontends
Support for new frontends can be added (even from outside this repo) by implementing the [`FCircuit` trait](https://github.com/privacy-scaling-explorations/sonobe/blob/main/folding-schemes/src/frontend/mod.rs).

folding-schemes/src/frontend/circom/mod.rs → 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<F: PrimeField> CircomFCircuit<F> {
fn fpvars_to_bigints(&self, fpVars: &[FpVar<F>]) -> Result<Vec<BigInt>, SynthesisError> {
fn fpvars_to_bigints(&self, fpvars: &[FpVar<F>]) -> Result<Vec<BigInt>, 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::<Fr>::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::<Fr>::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::<Fr>::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::<Fr>::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::<Fr>::new((r1cs_path.into(), wasm_path.into(), 3, 0)).unwrap();
let cs = ConstraintSystem::<Fr>::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::<Fr>::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()),

folding-schemes/src/frontend/circom/test_folder/circuits/is_zero.circom → frontends/src/circom/test_folder/circuits/is_zero.circom


+ 4
- 0
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/

folding-schemes/src/frontend/circom/test_folder/cubic_circuit.circom → frontends/src/circom/test_folder/cubic_circuit.circom


folding-schemes/src/frontend/circom/test_folder/no_external_inputs.circom → frontends/src/circom/test_folder/no_external_inputs.circom


folding-schemes/src/frontend/circom/test_folder/with_external_inputs.circom → frontends/src/circom/test_folder/with_external_inputs.circom


folding-schemes/src/frontend/circom/utils.rs → 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::<Fr>::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::<Fr>::new(r1cs_path.into(), wasm_path.into()).unwrap();

+ 3
- 0
frontends/src/lib.rs

@ -0,0 +1,3 @@
pub mod circom;
pub mod noir;
pub mod noname;

folding-schemes/src/frontend/noir/mod.rs → 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<F: PrimeField> FCircuit<F> for NoirFCircuit<F> {
type Params = (PathOrBin, usize, usize);
fn new(params: Self::Params) -> Result<Self, crate::Error> {
fn new(params: Self::Params) -> Result<Self, Error> {
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<F>,
external_inputs: Vec<F>, // inputs that are not part of the state
) -> Result<Vec<F>, crate::Error> {
) -> Result<Vec<F>, Error> {
let mut acvm = ACVM::new(
&StubbedBlackBoxSolver,
&self.circuit.opcodes,
@ -226,20 +224,21 @@ pub fn load_noir_circuit(path: String) -> Circuit
#[cfg(test)]
mod tests {
use crate::frontend::{noir::load_noir_circuit, FCircuit};
use crate::noir::load_noir_circuit;
use ark_bn254::Fr;
use ark_r1cs_std::R1CSVar;
use ark_r1cs_std::{alloc::AllocVar, fields::fp::FpVar};
use ark_relations::r1cs::ConstraintSystem;
use folding_schemes::frontend::FCircuit;
use std::env;
use crate::frontend::noir::NoirFCircuit;
use crate::noir::NoirFCircuit;
#[test]
fn test_step_native() {
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);
@ -259,7 +258,7 @@ mod tests {
let cs = ConstraintSystem::<Fr>::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::<Fr>::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);

folding-schemes/src/frontend/noir/test_folder/compile.sh → 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}

folding-schemes/src/frontend/noir/test_folder/test_circuit/Nargo.toml → frontends/src/noir/test_folder/test_circuit/Nargo.toml


folding-schemes/src/frontend/noir/test_folder/test_circuit/src/main.nr → frontends/src/noir/test_folder/test_circuit/src/main.nr


folding-schemes/src/frontend/noir/test_folder/test_mimc/Nargo.toml → frontends/src/noir/test_folder/test_mimc/Nargo.toml


folding-schemes/src/frontend/noir/test_folder/test_mimc/src/main.nr → frontends/src/noir/test_folder/test_mimc/src/main.nr


folding-schemes/src/frontend/noir/test_folder/test_no_external_inputs/Nargo.toml → frontends/src/noir/test_folder/test_no_external_inputs/Nargo.toml


folding-schemes/src/frontend/noir/test_folder/test_no_external_inputs/src/main.nr → frontends/src/noir/test_folder/test_no_external_inputs/src/main.nr


folding-schemes/src/frontend/noname/mod.rs → 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<F: PrimeField, BF: BackendField> FCircuit<F> for NonameFCircuit<F, BF> {
type Params = (String, usize, usize);
fn new(params: Self::Params) -> Result<Self, crate::Error> {
fn new(params: Self::Params) -> Result<Self, Error> {
let (code, state_len, external_inputs_len) = params;
let compiled_circuit = compile_source_code::<BF>(&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<F>,
external_inputs: Vec<F>,
) -> Result<Vec<F>, crate::Error> {
) -> Result<Vec<F>, 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;

folding-schemes/src/frontend/noname/utils.rs → frontends/src/noname/utils.rs


+ 1
- 0
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]

Loading…
Cancel
Save