Git Product home page Git Product logo

nova's Introduction

Nova: High-speed recursive arguments from folding schemes

Nova is a high-speed recursive SNARK (a SNARK is type cryptographic proof system that enables a prover to prove a mathematical statement to a verifier with a short proof and succinct verification, and a recursive SNARK enables producing proofs that prove statements about prior proofs).

Important

This project accepts external contributions, but please read this section before contributing.

More precisely, Nova achieves incrementally verifiable computation (IVC), a powerful cryptographic primitive that allows a prover to produce a proof of correct execution of a "long running" sequential computations in an incremental fashion. For example, IVC enables the following: The prover takes as input a proof $\pi_i$ proving the first $i$ steps of its computation and then update it to produce a proof $\pi_{i+1}$ proving the correct execution of the first $i + 1$ steps. Crucially, the prover's work to update the proof does not depend on the number of steps executed thus far, and the verifier's work to verify a proof does not grow with the number of steps in the computation. IVC schemes including Nova have a wide variety of applications such as Rollups, verifiable delay functions (VDFs), succinct blockchains, incrementally verifiable versions of verifiable state machines, and, more generally, proofs of (virtual) machine executions (e.g., EVM, RISC-V).

A distinctive aspect of Nova is that it is the simplest recursive proof system in the literature, yet it provides the fastest prover. Furthermore, it achieves the smallest verifier circuit (a key metric to minimize in this context): the circuit is constant-sized and its size is about 10,000 multiplication gates. Nova is constructed from a simple primitive called a folding scheme, a cryptographic primitive that reduces the task of checking two NP statements into the task of checking a single NP statement.

Details of the library

This repository provides nova-snark, a Rust library implementation of Nova over a cycle of elliptic curves. Our code supports three curve cycles: (1) Pallas/Vesta, (2) BN254/Grumpkin, and (3) secp/secq.

At its core, Nova relies on a commitment scheme for vectors. Compressing IVC proofs using Spartan relies on interpreting commitments to vectors as commitments to multilinear polynomials and prove evaluations of committed polynomials. Our code implements two commitment schemes and evaluation arguments:

  1. Pedersen commitments with IPA-based evaluation argument (supported on all three curve cycles), and
  2. HyperKZG commitments and evaluation argument (supported on curves with pairings e.g., BN254).

For more details on using HyperKZG, please see the test test_ivc_nontrivial_with_compression. The HyperKZG instantiation requires a universal trusted setup (the so-called "powers of tau"). In the setup method in src/provider/hyperkzg.rs, one can load group elements produced in an existing KZG trusted setup (that was created for other proof systems based on univariate polynomials such as Plonk or variants), but the library does not currently do so (please see this issue).

We also implement a SNARK, based on Spartan, to compress IVC proofs produced by Nova. There are two variants, one that does not use any preprocessing and another that uses preprocessing of circuits to ensure that the verifier's run time does not depend on the size of the step circuit.

Supported front-ends

A front-end is a tool to take a high-level program and turn it into an intermediate representation (e.g., a circuit) that can be used to prove executions of the program on concrete inputs. There are three supported ways to write high-level programs in a form that can be proven with Nova.

  1. bellpepper: The native APIs of Nova accept circuits expressed with bellpepper, a Rust toolkit to express circuits. See minroot.rs or sha256.rs for examples.

  2. Circom: A DSL and a compiler to transform high-level program expressed in its language into a circuit. There exist middleware to turn output of circom into a form suitable for proving with Nova. See Nova Scotia and Circom Scotia. In the future, we will add examples in the Nova repository to use these tools with Nova.

  3. Lurk: A Lisp dialect and a universal circuit to execute programs expressed in Lurk. The universal circuit can be proven with Nova.

In the future, we plan to support Noir, a Rust-like DSL and a compiler to transform those programs into an IR. See this GitHub issue for details.

Tests and examples

By default, we enable the asm feature of an underlying library (which boosts performance by up to 50%). If the library fails to build or run, one can pass --no-default-features to cargo commands noted below.

To run tests (we recommend the release mode to drastically shorten run times):

cargo test --release

To run an example:

cargo run --release --example minroot

References

The following paper, which appeared at CRYPTO 2022, provides details of the Nova proof system and a proof of security:

Nova: Recursive Zero-Knowledge Arguments from Folding Schemes
Abhiram Kothapalli, Srinath Setty, and Ioanna Tzialla
CRYPTO 2022

For efficiency, our implementation of the Nova proof system is instantiated over a cycle of elliptic curves. The following paper specifies that instantiation and provides a proof of security:

Revisiting the Nova Proof System on a Cycle of Curves
Wilson Nguyen, Dan Boneh, and Srinath Setty
IACR ePrint 2023/969

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Additional guidelines

This codebase implements a sophisticated cryptographic protocol, necessitating proficiency in cryptography, mathematics, security, and software engineering. Given the inherent complexity, the introduction of subtle bugs is a pervasive concern, rendering the acceptance of substantial contributions exceptionally challenging. Consequently, external contributors are kindly urged to submit incremental, easily reviewable pull requests (PRs) that encapsulate well-defined changes.

Our preference is to maintain code that is not only simple, but also easy to comprehend and maintain. This approach facilitates the auditing of code for correctness and security. To achieve this objective, we may prioritize code simplicity over minor performance enhancements, particularly when such improvements entail intricate, challenging-to-maintain code that disrupts abstractions.

In the event that you propose performance-related changes through a PR, we anticipate the inclusion of reproducible benchmarks demonstrating substantial speedups across a range of typical circuits. This rigorous benchmarking ensures that the proposed changes meaningfully enhance the performance of a diverse set of applications built upon Nova. Each performance enhancement will undergo a thorough, case-by-case evaluation to ensure alignment with our commitment to maintaining codebase simplicity.

Lastly, should you intend to submit a substantial PR, we kindly request that you initiate a GitHub issue outlining your planned changes, thereby soliciting feedback prior to committing substantial time to the implementation of said changes.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

Acknowledgments

See the contributors list here

nova's People

Contributors

3for avatar arthurgreef avatar ashwhitehat avatar bingcicle avatar chiro-hiro avatar dignifiedquire avatar dmpierre avatar field-worker avatar flyq avatar gooddaisy avatar hero78119 avatar huitseeker avatar iontzialla avatar jbearer avatar jun-hee-lee avatar leonardoalt avatar microsoftopensource avatar mmaker avatar nalinbhardwaj avatar oskarth avatar porcuquine avatar ryankung avatar samuelburnham avatar shuoer86 avatar srinathsetty avatar storojs72 avatar thelitfire avatar varunthakore avatar xiaolou86 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nova's Issues

Compilation on 32-bit architectures

Hi all,

Thanks for the very cool project. Has anyone tried to compile Nova for a 32-bit architecture? I think it has a transitive dependency somewhere on an older version of typenum that uses const generic usize greater than usize::MAX on 32-bit machines. Just wondering if anyone has found a simple workaround.

Thanks!

Patrick

compiling to solidity/evm?

hey this library looks great. we are looking for a "next gen" circom library for implementing smart contracts on blockchains. Do you have any plans going forward to support compiling to other languages such as solidity/huff?

Zero-knowledge implementation gap

As outlined in the Lurk audit report, the variants of the IPA and Spartan in the repository do not provide zero-knowledge (unlike the sum-check in the original Spartan repository).

In particular, the IPA needs to be updated to use blinding commitments and the sum-check inside Spartan needs to be made hiding.

At a more abstract level, Hyrax offers a blueprint on how to make the sum-check zero-knowledge.

Modules are not public

Hi - the circuit, gadgets, and poseidon modules are not public. Can we make them public?

pub mod bellperson;
mod circuit;
pub mod errors;
mod gadgets;
pub mod pasta;
mod poseidon;
pub mod r1cs;
pub mod traits;

Middleware to load Noir's ACIR into R1CS supported by Nova

Nova accepts circuits written with bellpepper. If one writes a middleware (analogous to Noir's arkworks backend) to parse and load ACIR (and witness) into a bellpepper circuit, one can then prove the execution of Noir programs with Nova.

In nifs.rs's test_tiny_r1cs() case, why the num_vars = 4?

I think there only are Z0, Z1, Z3 3 variables, so the num_vars should be 3.

fn test_tiny_r1cs() {
    let one = S::one();
    let (num_cons, num_vars, num_io, A, B, C) = {
      let num_cons = 4;  
      let num_vars = 4;
      let num_io = 2;

      // Consider a cubic equation: `x^3 + x + 5 = y`, where `x` and `y` are respectively the input and output.
      // The R1CS for this problem consists of the following constraints:
      // `I0 * I0 - Z0 = 0`
      // `Z0 * I0 - Z1 = 0`
      // `(Z1 + I0) * 1 - Z2 = 0`
      // `(Z2 + 5) * 1 - I1 = 0`
     .... 

Unclear UnSat Error: 'RecursiveSNARK::verify: Err(UnSat)'

Following examples found in NovaScotia and I get error UnSat, that following Nova docs means: returned if the supplied witness is not a satisfying witness to a given shape and instance.

The circuit is proved correctly but when it comes to verify it, this problems comes out with the witness verification. I have literally no idea on where the problem is as the circuit is proved correctly and should be verified correctly too, is there as step that I am missing with the primary or secondary curves inputs, for the secondary I am just passing 0 as I have no idea what it does (but can see that if I pass any other number I get ProofVerifyError, which tells me that the 0 might be on the right road)

I am using NovaScotia to compile a recursiveSnark from my Circom circuit and then using Nova to verify and compress the proof.

This is my script code:


use std::{
    collections::HashMap,
    env::current_dir,
    io::Write,
    time::{Duration, Instant},
};
use babyjubjub_rs::Point;
use pasta_curves::group::ff::PrimeField;

use nova_scotia::{
    circom::reader::load_r1cs, create_public_params, create_recursive_circuit, FileLocation, F
};
use nova_snark::{
    traits::{circuit::TrivialTestCircuit, Group},
    CompressedSNARK, PublicParams, RecursiveSNARK,
};
use serde::{Deserialize, Serialize};
use serde_json::json;
use poseidon_rs::{Fr, Poseidon};

#[derive(Serialize, Deserialize)]
#[allow(non_snake_case)]
struct ProofInput {
    step_in: Vec<String>,
    newData: Vec<String>,
    nextUserBehavioralProfileCommitments: Vec<String>,
    r8x: String,
    r8y: String,
    s: String,
}

fn bench() -> (Duration, Duration) {
    type G1 = pasta_curves::pallas::Point;
    type G2 = pasta_curves::vesta::Point;
    let root = current_dir().unwrap();

    let circuit_file = root.join("../build/recursiveLogin.r1cs");

    let r1cs = load_r1cs::<G1, G2>(&FileLocation::PathBuf(circuit_file));
    let witness_generator_file =
        root.join("../build/recursiveLogin_js/recursiveLogin.wasm");


    // load serde json
    let users_data: Vec<ProofInput> =
        serde_json::from_str(include_str!("fetcher/loginsInputs.json")).unwrap();
    let iteration_count: usize = users_data.len();

    let start_public_input = [
        F::<G1>::from_str_vartime(&users_data[0].step_in[0]).unwrap(),
        F::<G1>::from_str_vartime(&users_data[0].step_in[1]).unwrap(),
        F::<G1>::from_str_vartime(&users_data[0].step_in[2]).unwrap(),
        F::<G1>::from_str_vartime(&users_data[0].step_in[3]).unwrap()
    ];

    let mut private_inputs = Vec::new();

    for i in 0..users_data.len() {
        let mut private_input = HashMap::new();
        private_input.insert(
            "newData".to_string(),
            json!(
                users_data[i].newData
            ),
            //(0..lengthNewData).map(|j| F1::from_raw(&usersData[i].newData[j]).unwrap()).collect();
        );
        private_input.insert(
            "S".to_string(),
            json!(users_data[i].s)
        );
        private_input.insert(
            "R8x".to_string(),
            json!(users_data[i].r8x)
        );
        private_input.insert(
            "R8y".to_string(),
            json!(users_data[i].r8y)
        );
        let mut nextUserBehavioralProfileCommitments = Vec::new();

        nextUserBehavioralProfileCommitments.extend_from_slice(&users_data[i].nextUserBehavioralProfileCommitments);

        private_input.insert(
            "nextUserBehavioralProfileCommitments".to_string(),
            json!(
                nextUserBehavioralProfileCommitments
            ),
        );
        private_inputs.push(private_input);
    }

     println!("{:?} {:?}", start_public_input, private_inputs);

    let pp = create_public_params(r1cs.clone());

    println!(
        "Number of constraints per step (primary circuit): {}",
        pp.num_constraints().0
    );
    println!(
        "Number of constraints per step (secondary circuit): {}",
        pp.num_constraints().1
    );

    println!(
        "Number of variables per step (primary circuit): {}",
        pp.num_variables().0
    );
    println!(
        "Number of variables per step (secondary circuit): {}",
        pp.num_variables().1
    );

    println!("witness_generator_file {:?}", witness_generator_file);

    println!("Creating a RecursiveSNARK...");
    let start = Instant::now();
    let recursive_snark = create_recursive_circuit(
        FileLocation::PathBuf(witness_generator_file),
        r1cs,
        private_inputs,
        start_public_input.to_vec(),
        &pp,
    )
    .unwrap();
    let prover_time = start.elapsed();
    println!("RecursiveSNARK creation took {:?}", start.elapsed());

    let z0_secondary = [<G2 as Group>::Scalar::zero()];

    // verify the recursive SNARK
    println!("Verifying a RecursiveSNARK...");
    let start = Instant::now();
    let res = recursive_snark.verify(
        &pp,
        iteration_count,
        &start_public_input,
        &z0_secondary,
    );
    println!(
        "RecursiveSNARK::verify: {:?}, took {:?}",
        res,
        start.elapsed()
    );
    let verifier_time = start.elapsed();
    assert!(res.is_ok());

    // produce a compressed SNARK
    println!("Generating a CompressedSNARK using Spartan with IPA-PC...");
    let (pk, vk) = CompressedSNARK::<_, _, _, _, S1, S2>::setup(&pp).unwrap();

    // produce a compressed SNARK
    println!("Generating a CompressedSNARK using Spartan with IPA-PC...");
    let start = Instant::now();
    type EE1 = nova_snark::provider::ipa_pc::EvaluationEngine<G1>;
    type EE2 = nova_snark::provider::ipa_pc::EvaluationEngine<G2>;
    type S1 = nova_snark::spartan::snark::RelaxedR1CSSNARK<G1, EE1>;
    type S2 = nova_snark::spartan::snark::RelaxedR1CSSNARK<G2, EE2>;
    let res = CompressedSNARK::<_, _, _, _, S1, S2>::prove(&pp, &pk, &recursive_snark);
    println!(
        "CompressedSNARK::prove: {:?}, took {:?}",
        res.is_ok(),
        start.elapsed()
    );
    assert!(res.is_ok());
    let compressed_snark = res.unwrap();

    // verify the compressed SNARK
    println!("Verifying a CompressedSNARK...");
    let start = Instant::now();
    let res = compressed_snark.verify(
        &vk,
        iteration_count,
        start_public_input.clone().to_vec(),
        z0_secondary.to_vec(),
    );
    println!(
        "CompressedSNARK::verify: {:?}, took {:?}",
        res.is_ok(),
        start.elapsed()
    );
    assert!(res.is_ok());
    let serialized_compressed_snark = serde_json::to_string(&compressed_snark).unwrap();

    (prover_time, verifier_time)
}

fn main() {
    // create benchmark file
    let mut file = std::fs::File::create("src/benchmark.csv").unwrap();
    file.write_all(b"iteration_count,prover_time,verifier_time\n")
        .unwrap();
    let iteration_count = 100;

        // run bash script
        /* std::process::Command::new("bash")
            .arg("../scripts/circom/compile.sh")
            .arg(i.to_string())
            .output()
            .expect("failed to execute process"); */

    let (prover_time, verifier_time) = bench();
    file.write_all(format!("{},{:?},{:?}\n", iteration_count, prover_time, verifier_time).as_bytes())
        .unwrap();
}

I get

Number of constraints per step (primary circuit): 15892
Number of constraints per step (secondary circuit): 10347
Number of variables per step (primary circuit): 16659
Number of variables per step (secondary circuit): 10329
witness_generator_file "/Users/vlaca/Documents/work/innerworks/zero-knowledge/zk/nova/../build/recursiveLogin_js/recursiveLogin.wasm"
Creating a RecursiveSNARK...
RecursiveSNARK creation took 1.677693459s
Verifying a RecursiveSNARK...
RecursiveSNARK::verify: Err(UnSat), took 104.866ms
thread 'main' panicked at 'assertion failed: res.is_ok()', src/main.rs:165:5

The UnSat error really does not tell me much and I am stuck

Remove redundant absorbing to the transcript

One of CompressedSNARK's verification steps (affects only ppspartan.rs) - checking the satisfiability of the folded instances (link) - has following redundant absorption of eval_vec to the transcript, since it is already happened here. Absorbing the same value twice adds no new entropy to the transcript, so second one can be freely removed.

I'm happy to provide a hotfix for this in case if core contributors confirm the issue

Guidance on Using Poseidon Hash in Custom Circuits

I'm trying to incorporate Poseidon hash functionality into my own custom circuits. However, I'm facing some challenges and could use some guidance on how to properly integrate and utilize the Poseidon hash circuit.

Steps to Reproduce:
Attempt to incorporate Poseidon hash into a custom circuit.
Encounter difficulties in understanding the integration process and utilizing the hash algorithm effectively.
Struggle to find relevant documentation or examples within the Nova repository that specifically address the usage of Poseidon hash in custom circuits.

Expected Behavior:
I would appreciate some guidance or documentation on how to effectively incorporate and utilize the Poseidon hash algorithm in custom circuits within the Nova repository. This would enable me to leverage the benefits of Poseidon hash within my own custom circuit designs.

Clippy gave different result depend on the version of compiler and clippy

cargo clippy --all-targets -- -D warnings this check on CI/CD and my computer are giving different result. Are there any work around to keep other people in the same page?.

rustc 1.70.0 (90c541806 2023-05-31)
clippy 0.1.70 (90c54180 2023-05-31)

Here is my result:

442 |     let mut acc = p.clone();
    |                    ^^^^^^^^ help: remove this
    |
note: cloned value is neither consumed nor mutated
   --> src/gadgets/ecc.rs:442:19
    |
442 |     let mut acc = p.clone();
    |                   ^^^^^^^^^
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone
note: the lint level is defined here
   --> src/lib.rs:3:3
    |
3   |   warnings,
    |   ^^^^^^^^
    = note: `#[deny(clippy::redundant_clone)]` implied by `#[deny(warnings)]`

error: could not compile `nova-snark` (lib) due to previous error
warning: build failed, waiting for other jobs to finish...
error: redundant clone
    --> src/gadgets/ecc.rs:1070:18
     |
1070 |     let mut b = a.clone();
     |                  ^^^^^^^^ help: remove this
     |
note: cloned value is neither consumed nor mutated
    --> src/gadgets/ecc.rs:1070:17
     |
1070 |     let mut b = a.clone();
     |                 ^^^^^^^^^
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone

error: could not compile `nova-snark` (lib test) due to 2 previous errors

Improve the interface of `RecursiveSNARK` with `ParamContext` and `ProvingContext`

As the suggestion from @huitseeker, I submit this proposal to improve RecursiveSNARK a bit further.

Motivation

Improve the interface of RecursiveSNARK to make it more friendly to use. The current interface is keep passing many values as parameters meanwhile it should be a part of internal context.

Specification

Here is how RecursiveSNARK looks for now.

    // produce a recursive SNARK
    let mut recursive_snark = RecursiveSNARK::<
      G1,
      G2,
      TrivialTestCircuit<<G1 as Group>::Scalar>,
      CubicCircuit<<G2 as Group>::Scalar>,
    >::new(
      &pp,
      &circuit_primary,
      &circuit_secondary,
      vec![<G1 as Group>::Scalar::ONE],
      vec![<G2 as Group>::Scalar::ZERO],
    );

    for _i in 0..num_steps {
      let res = recursive_snark.prove_step(
        &pp,
        &circuit_primary,
        &circuit_secondary,
        vec![<G1 as Group>::Scalar::ONE],
        vec![<G2 as Group>::Scalar::ZERO],
      );
      assert!(res.is_ok());
    }

    // verify the recursive SNARK
    let res = recursive_snark.verify(
      &pp,
      num_steps,
      &[<G1 as Group>::Scalar::ONE],
      &[<G2 as Group>::Scalar::ZERO],
    );

You may notice this ugly code in my pull request #163.

    // Frist step was already done in the constructor
    if self.i == 0 {
      self.i = 1;
      return Ok(());
    }

To solve everything completly, I propose to have two major changes.

1. Add a ParamContext struct

struct ParamContext<G1, G2, C1, C2>
where
  G1: Group<Base = <G2 as Group>::Scalar>,
  G2: Group<Base = <G1 as Group>::Scalar>,
  C1: StepCircuit<G1::Scalar>,
  C2: StepCircuit<G2::Scalar>, {
    public_param: &PublicParams<G1, G2, C1, C2>,
    c_primary: &C1,
    c_secondary: &C2,
    z0_primary: Vec<G1::Scalar>,
    z0_secondary: Vec<G2::Scalar>,
}

The ParamContext and is a part of RecursiveSNARK struct. The interface will be changed, and look like this.

    // produce a recursive SNARK
    let mut recursive_snark = RecursiveSNARK::<
      G1,
      G2,
      TrivialTestCircuit<<G1 as Group>::Scalar>,
      CubicCircuit<<G2 as Group>::Scalar>,
    >::new(
      &pp,
      &circuit_primary,
      &circuit_secondary,
    );

    for _i in 0..num_steps {
      let res = recursive_snark.prove_step();
      assert!(res.is_ok());
    }

    // verify the recursive SNARK
    let res = recursive_snark.verify();

2. Add a ProvingContext struct

pub struct ProvingContext<G1, G2, C1, C2>
where
  G1: Group<Base = <G2 as Group>::Scalar>,
  G2: Group<Base = <G1 as Group>::Scalar>,
  C1: StepCircuit<G1::Scalar>,
  C2: StepCircuit<G2::Scalar>,
{
  r_W_primary: RelaxedR1CSWitness<G1>,
  r_U_primary: RelaxedR1CSInstance<G1>,
  r_W_secondary: RelaxedR1CSWitness<G2>,
  r_U_secondary: RelaxedR1CSInstance<G2>,
  l_w_secondary: R1CSWitness<G2>,
  l_u_secondary: R1CSInstance<G2>,
  i: usize,
  zi_primary: Vec<G1::Scalar>,
  zi_secondary: Vec<G2::Scalar>,
  _p_c1: PhantomData<C1>,
  _p_c2: PhantomData<C2>,
}

These two new structs will be used to store the context of proving and parameters. The RecursiveSNARK struct will be changed to this. By making ProvingContext is an optional, we can get rid of the ugly code in the pull request #163.

pub struct RecursiveSNARK<G1, G2, C1, C2>
where
  G1: Group<Base = <G2 as Group>::Scalar>,
  G2: Group<Base = <G1 as Group>::Scalar>,
  C1: StepCircuit<G1::Scalar>,
  C2: StepCircuit<G2::Scalar>,
{
  ctx_param: Arc<Mutex<ParamContext<G1, G2, C1, C2>>>,
  ctx_proving: Option<ProvingContext<G1, G2, C1, C2>>,
}

Consideration

  • We need to deal with lifetime of the borrowed values in struct.
  • We should consider to use Arc and Mutex to keep a single instance of ParamContext.
  • Serialized/deserialized will be affect by this change.
  • We might need to add new methods to access these contexts (proving_steps, z0_primary, z0_secondary...)

Move to actual `group` traits and create `GroupExt` for the extra extensions of the `Group` trait

One thing I've noticed and it's quite confusing from this repo is that it re-implements the Group trait.
I've been playing arround with this and I think it should be possible to use the original group::Group trait and create here a GroupExt trait that extends the missing features of Group to be able to do everything needed (have the attached commitment scheme traits for example..).

This would reduce duplication of code and also reduce the complexity of the lib significantly. Also, we can later check with the Zcash people to see which things would make sense to upstream to their group crate.

If that's something interesting, I'd love to work on it! So just let me know!

error: could not compile `nova-snark` (lib test) due to previous error

When I tried this command: cargo test --release, I met this error.
How can I solve it?

error: linking with `cc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/lq/.vscode-server/bin/1a5daa3a0231a0fbba4f14db7ec463cf99d7768e/bin/remote-cli:/home/lq/anaconda3/envs/torch/bin:/home/lq/anaconda3/condabin:/home/lq/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/lq/anaconda3/bin:/home/lq/.vscode-server/bin/1a5daa3a0231a0fbba4f14db7ec463cf99d7768e/bin/remote-cli:/home/lq/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" VSLANG="1033" "cc" "-m64" "/tmp/rustcgDx255/symbols.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.00.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.01.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.02.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.03.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.04.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.05.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.06.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.07.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.08.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.09.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.10.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.11.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.12.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.13.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.14.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.nova_snark.b23c3e9fd8311171-cgu.15.rcgu.o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c.27738q150i0litpz.rcgu.o" "-Wl,--as-needed" "-L" "/home/lq/project/Nova/target/release/deps" "-L" "/home/lq/project/Nova/target/release/build/pasta-msm-5889b0d5905c3345/out" "-L" "/home/lq/project/Nova/target/release/build/pasta-msm-5889b0d5905c3345/out" "-L" "/home/lq/project/Nova/target/release/build/pasta-msm-5889b0d5905c3345/out" "-L" "/home/lq/project/Nova/target/release/build/semolina-742fe02cb979602c/out" "-L" "/home/lq/project/Nova/target/release/build/sppark-2309c16a02d6afbc/out" "-L" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/lq/project/Nova/target/release/deps/libpasta_msm-7fcf8e95f38040ea.rlib" "/home/lq/project/Nova/target/release/deps/libsppark-69bd22a88f96a875.rlib" "/home/lq/project/Nova/target/release/deps/libsemolina-8fefc018f6f918c9.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libtest-1c1e90653c657ff2.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgetopts-e8683e75aaaef901.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunicode_width-b71c2483f91f7b1d.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_std-0501fbcc95f3e2d1.rlib" "/home/lq/project/Nova/target/release/deps/libneptune-9f77a831dc55cfdf.rlib" "/home/lq/project/Nova/target/release/deps/libhalo2curves-eb2f9eb874c3fef3.rlib" "/home/lq/project/Nova/target/release/deps/libserde_arrays-4cb1b7cb62cd8a98.rlib" "/home/lq/project/Nova/target/release/deps/libpairing-38cd24ff632722b1.rlib" "/home/lq/project/Nova/target/release/deps/libnum_bigint-ca3b75e6279386d1.rlib" "/home/lq/project/Nova/target/release/deps/libnum_integer-02dabb58ac9a8f9d.rlib" "/home/lq/project/Nova/target/release/deps/libnum_traits-f56b94a3e4e42668.rlib" "/home/lq/project/Nova/target/release/deps/libpasta_curves-22d4b99f1cba5bed.rlib" "/home/lq/project/Nova/target/release/deps/libhex-92eb3f38aa65df99.rlib" "/home/lq/project/Nova/target/release/deps/libblake2b_simd-769f6188e1774bd4.rlib" "/home/lq/project/Nova/target/release/deps/libstatic_assertions-eab2eb1c9c5479e2.rlib" "/home/lq/project/Nova/target/release/deps/libgroup-f52deb0b523f840e.rlib" "/home/lq/project/Nova/target/release/deps/libproptest-e9e14c71c39dfea7.rlib" "/home/lq/project/Nova/target/release/deps/libunarray-930df28a80245de6.rlib" "/home/lq/project/Nova/target/release/deps/libregex_syntax-ca2fc63a08bab674.rlib" "/home/lq/project/Nova/target/release/deps/librand_xorshift-a0231543f33c0ade.rlib" "/home/lq/project/Nova/target/release/deps/librusty_fork-f84ea28503e8349f.rlib" "/home/lq/project/Nova/target/release/deps/libwait_timeout-03147b3b2b354db2.rlib" "/home/lq/project/Nova/target/release/deps/libtempfile-ca22a25e64ad14c8.rlib" "/home/lq/project/Nova/target/release/deps/libfastrand-f6661ca0d6f249f5.rlib" "/home/lq/project/Nova/target/release/deps/librustix-912deacfa059db75.rlib" "/home/lq/project/Nova/target/release/deps/liblinux_raw_sys-1ff8d5e0dbfc894e.rlib" "/home/lq/project/Nova/target/release/deps/libfnv-bcb4d596ed096a87.rlib" "/home/lq/project/Nova/target/release/deps/libquick_error-4fc32a8408c2d16b.rlib" "/home/lq/project/Nova/target/release/deps/liblazy_static-0985704e5d19b294.rlib" "/home/lq/project/Nova/target/release/deps/libspin-5794b69290b3a4d7.rlib" "/home/lq/project/Nova/target/release/deps/libbit_set-473a87f64092db5f.rlib" "/home/lq/project/Nova/target/release/deps/libbit_vec-2f14fa5fd3e62d6a.rlib" "/home/lq/project/Nova/target/release/deps/libbitflags-68fc6e412662e218.rlib" "/home/lq/project/Nova/target/release/deps/librayon-b7e849bd61a4c808.rlib" "/home/lq/project/Nova/target/release/deps/librayon_core-27a5c271e81020de.rlib" "/home/lq/project/Nova/target/release/deps/libcrossbeam_deque-cd8463d2b2eb8a73.rlib" "/home/lq/project/Nova/target/release/deps/libcrossbeam_epoch-d91e271b0088a611.rlib" "/home/lq/project/Nova/target/release/deps/libmemoffset-5f7b838a078e3d38.rlib" "/home/lq/project/Nova/target/release/deps/libscopeguard-96448b6b16196307.rlib" "/home/lq/project/Nova/target/release/deps/libcrossbeam_utils-4410ffc4125e3119.rlib" "/home/lq/project/Nova/target/release/deps/libeither-b86b04317cb0dd22.rlib" "/home/lq/project/Nova/target/release/deps/librand-f31ae72b5ad979fd.rlib" "/home/lq/project/Nova/target/release/deps/librand_chacha-c068f3349281af46.rlib" "/home/lq/project/Nova/target/release/deps/libppv_lite86-08381a55bf8c473c.rlib" "/home/lq/project/Nova/target/release/deps/libonce_cell-d1afd78e8c78f842.rlib" "/home/lq/project/Nova/target/release/deps/libsha3-de734461d667ee11.rlib" "/home/lq/project/Nova/target/release/deps/libkeccak-05889a19997fa8eb.rlib" "/home/lq/project/Nova/target/release/deps/libdigest-d91f9cb0b9b67ce3.rlib" "/home/lq/project/Nova/target/release/deps/libblock_buffer-1247fb3e55eeb882.rlib" "/home/lq/project/Nova/target/release/deps/libcrypto_common-c79e76e394085203.rlib" "/home/lq/project/Nova/target/release/deps/libgeneric_array-47e3a94764cdb11d.rlib" "/home/lq/project/Nova/target/release/deps/libtypenum-ef8ef4f80e5cf562.rlib" "/home/lq/project/Nova/target/release/deps/libbincode-fbf879090449b81c.rlib" "/home/lq/project/Nova/target/release/deps/libbellpepper-589db2b950baf7dd.rlib" "/home/lq/project/Nova/target/release/deps/libbellpepper_core-0b58774cc9298b3d.rlib" "/home/lq/project/Nova/target/release/deps/libthiserror-763af02620695299.rlib" "/home/lq/project/Nova/target/release/deps/libblake2s_simd-137ef07b2ff0a11c.rlib" "/home/lq/project/Nova/target/release/deps/libconstant_time_eq-fd7b208ecd3f9063.rlib" "/home/lq/project/Nova/target/release/deps/libarrayvec-a2f44900e8cb9332.rlib" "/home/lq/project/Nova/target/release/deps/libarrayref-8a61eb916e5818b0.rlib" "/home/lq/project/Nova/target/release/deps/libserde-f837ad590d79821a.rlib" "/home/lq/project/Nova/target/release/deps/libff-c674d524e1292192.rlib" "/home/lq/project/Nova/target/release/deps/libbyteorder-d4dc81402f587e5e.rlib" "/home/lq/project/Nova/target/release/deps/librand_core-7abc281b267db03b.rlib" "/home/lq/project/Nova/target/release/deps/libgetrandom-c55aeeb6b06312f3.rlib" "/home/lq/project/Nova/target/release/deps/liblibc-477d49ee0a9e3f70.rlib" "/home/lq/project/Nova/target/release/deps/libcfg_if-17709ab0e2f45da0.rlib" "/home/lq/project/Nova/target/release/deps/libbitvec-d623938ca4bca493.rlib" "/home/lq/project/Nova/target/release/deps/libwyz-74412a8aa5534b87.rlib" "/home/lq/project/Nova/target/release/deps/libtap-d63c521426b4b08e.rlib" "/home/lq/project/Nova/target/release/deps/libradium-f3f9c2f450bec65d.rlib" "/home/lq/project/Nova/target/release/deps/libfunty-fa8684eb7221f148.rlib" "/home/lq/project/Nova/target/release/deps/libsubtle-1a8b60b7805013ad.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-6498d8891e016dca.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-3debdee1a9058d84.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-8339c5bd5cbc92bf.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libmemchr-160ebcebb54c11ba.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-95c75789f1b65e37.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-7e8094f2d6258832.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-bac9783ef1b45db0.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-a1cd87df2f2d8e76.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-7fd06d468d7dba16.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-5ac19487656e05bf.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-c7c35d32cf825c11.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-c523f1571362e70b.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-85f17c92b770a911.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-598d3ba148dadcea.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-a58ec2dab545caa4.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-f9dda8cca149f0fc.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-7ba4c315dd7a3503.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-5ac2993e19124966.rlib" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-df2fb7f50dec519a.rlib" "-Wl,-Bdynamic" "-lstdc++" "-lcudart_static" "-lstdc++" "-lcudart_static" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/lq/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/lq/project/Nova/target/release/deps/nova_snark-0a97af52b066276c" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-nodefaultlibs"
  = note: /usr/bin/ld: /home/lq/project/Nova/target/release/deps/libpasta_msm-7fcf8e95f38040ea.rlib(pallas.o): in function `msm_t<xyzz_t<pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one>, pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> >, jacobian_t<pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> >, xyzz_t<pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one>, pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> >::affine_t, pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one>, xyzz_t<pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one>, pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> >::affine_t::mem_t, xyzz_t<pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one>, pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> >::mem_t>::invoke(jacobian_t<pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> >&, xyzz_t<pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one>, pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> >::affine_t const*, unsigned long, pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> const*, bool, unsigned long) [clone .constprop.0]':
          tmpxft_0002ca00_00000000-6_pallas.cudafe1.cpp:(.text._ZN5msm_tI6xyzz_tI7pasta_tIXadL_ZL8Pallas_PEELy11037532056220336127EXadL_ZL9Pallas_RREEXadL_ZL10Pallas_oneEEES2_E10jacobian_tIS2_ENS3_8affine_tES1_IXadL_ZL7Vesta_PEELy10108024940646105087EXadL_ZL8Vesta_RREEXadL_ZL9Vesta_oneEEENS6_5mem_tENS3_5mem_tEE6invokeERS5_PKS6_mPKS7_bm.constprop.0+0xf67): undefined reference to `cudaMallocAsync'
          /usr/bin/ld: /home/lq/project/Nova/target/release/deps/libpasta_msm-7fcf8e95f38040ea.rlib(pallas.o): in function `cuda_pippenger_pallas.cold':
          tmpxft_0002ca00_00000000-6_pallas.cudafe1.cpp:(.text.unlikely.cuda_pippenger_pallas+0x446): undefined reference to `cudaFreeAsync'
          /usr/bin/ld: /home/lq/project/Nova/target/release/deps/libpasta_msm-7fcf8e95f38040ea.rlib(pallas.o): in function `cuda_pippenger_pallas':
          tmpxft_0002ca00_00000000-6_pallas.cudafe1.cpp:(.text.cuda_pippenger_pallas+0x109): undefined reference to `cudaMallocAsync'
          /usr/bin/ld: tmpxft_0002ca00_00000000-6_pallas.cudafe1.cpp:(.text.cuda_pippenger_pallas+0x1db): undefined reference to `cudaFreeAsync'
          /usr/bin/ld: /home/lq/project/Nova/target/release/deps/libpasta_msm-7fcf8e95f38040ea.rlib(vesta.o): in function `msm_t<xyzz_t<pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one>, pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> >, jacobian_t<pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> >, xyzz_t<pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one>, pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> >::affine_t, pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one>, xyzz_t<pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one>, pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> >::affine_t::mem_t, xyzz_t<pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one>, pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> >::mem_t>::invoke(jacobian_t<pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> >&, xyzz_t<pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one>, pasta_t<&Vesta_P, 10108024940646105087ull, &Vesta_RR, &Vesta_one> >::affine_t const*, unsigned long, pasta_t<&Pallas_P, 11037532056220336127ull, &Pallas_RR, &Pallas_one> const*, bool, unsigned long) [clone .constprop.0]':
          tmpxft_0002cc17_00000000-6_vesta.cudafe1.cpp:(.text._ZN5msm_tI6xyzz_tI7pasta_tIXadL_ZL7Vesta_PEELy10108024940646105087EXadL_ZL8Vesta_RREEXadL_ZL9Vesta_oneEEES2_E10jacobian_tIS2_ENS3_8affine_tES1_IXadL_ZL8Pallas_PEELy11037532056220336127EXadL_ZL9Pallas_RREEXadL_ZL10Pallas_oneEEENS6_5mem_tENS3_5mem_tEE6invokeERS5_PKS6_mPKS7_bm.constprop.0+0xf67): undefined reference to `cudaMallocAsync'
          /usr/bin/ld: /home/lq/project/Nova/target/release/deps/libpasta_msm-7fcf8e95f38040ea.rlib(vesta.o): in function `cuda_pippenger_vesta.cold':
          tmpxft_0002cc17_00000000-6_vesta.cudafe1.cpp:(.text.unlikely.cuda_pippenger_vesta+0x446): undefined reference to `cudaFreeAsync'
          /usr/bin/ld: /home/lq/project/Nova/target/release/deps/libpasta_msm-7fcf8e95f38040ea.rlib(vesta.o): in function `cuda_pippenger_vesta':
          tmpxft_0002cc17_00000000-6_vesta.cudafe1.cpp:(.text.cuda_pippenger_vesta+0x109): undefined reference to `cudaMallocAsync'
          /usr/bin/ld: tmpxft_0002cc17_00000000-6_vesta.cudafe1.cpp:(.text.cuda_pippenger_vesta+0x1db): undefined reference to `cudaFreeAsync'
          collect2: error: ld returned 1 exit status
          
  = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

error: could not compile `nova-snark` (lib test) due to previous error

Compilation error: failed to select a version for the requirement `funty = "~1.2"`

Full compilation error:

error: failed to select a version for the requirement `funty = "~1.2"`
candidate versions found which didn't match: 2.0.0, 1.1.0, 1.0.1, ...
location searched: crates.io index
required by package `bitvec v0.22.3`
    ... which satisfies dependency `bitvec = "^0.22.3"` of package `ec-gpu-gen v0.3.0`
    ... which satisfies dependency `ec-gpu-gen = "^0.3.0"` of package `bellperson v0.22.0`
    ... which satisfies dependency `bellperson = "^0.22"` of package `bellperson-nonnative v0.3.1`
    ... which satisfies dependency `bellperson-nonnative = "^0.3.1"` of package `nova-snark v0.8.1 (/home/t490/programs/Nova)`

For an amusing history which led to this issue, I think this is relevant: ferrilab/funty#3

TL;DR, seems as if they killed funty version 1.2 5 days ago.

I think using bellperson = "0.24.0" (and updating bellperson-nonnative to also use this bellperson) will solve it.

Why the type of "x" is vector?

Hi, I've been interested in the paper, and I've been looking at the implementation.
i have a question about type of instance.

in my knowledge, i think the type of x should be G::Scalar not Vector!
is this have any reason using Vec?
I want to know if I miss anything
Thank you

pub struct RelaxedR1CSInstance<G: Group> {
pub(crate) comm_W: Commitment,
pub(crate) comm_E: Commitment,
pub(crate) X: Vec<G::Scalar>,
pub(crate) u: G::Scalar,
}

Does Nova support local statements (public inputs) to step function F?

Hi there, thanks for this awesome project!

I am trying to build a circuit that computes the digest of a long string, which is done via recursively absorbing new data chunks into existing state. That is, $h := H(\cdots H(H(s, x_1), x_2) \cdots, x_n)$, where $x_1, \cdots, x_n$ are supposed to be statements (i.e., public inputs).

However, it seemed that Nova didn't not allow passing local statements to the circuit in each step, as enforced in these lines. I also checked Nova's original paper, where the input to $F$ is solely the output of the previous round. The eprint 2023/969 paper includes auxiliary values in the IVC definition, but these values are secret witnesses if I understand correctly.

Is there any workaround to support my use case, where the step function takes additional local statements? Thanks!

Re-export Field/Point types used in curve cycle implementations

#267 made the provider modules, notably the two field types and the two point types for each curve cycle, private, only exposing the Engine.

However, downstream users of nova may eventually need to use a distinct version of the libraries Nova uses for those providers, and should they not be able to exactly match that version, they would no longer have a handle on those field and point types, which would make them incapable of implementing traits on them, etc.

See https://www.lurklurk.org/effective-rust/re-export.html for a comprehensive description of this issue.

A good practice would be to re-export either the entire dependency crates (pasta_curves, halo2curves) or the four core types used in the provider module. The bn256_grumpkin cycle, for instance, forms a handy set of aliases (aimed at making the halo2curves types amenable to the nova curves macros) that could be re-exported:

pub mod bn256 {
pub use halo2curves::bn256::{Fq as Base, Fr as Scalar, G1Affine as Affine, G1 as Point};
}

Can we change alloc_num_equals args to references?

I get references to AllocatedNum when I call get_coordinates on AllocatedPoint. I get borrow errors when I try to dereference the coordinates when I call this function.

Change this

pub fn alloc_num_equals<F: PrimeField, CS: ConstraintSystem<F>>(
  mut cs: CS,
  a: AllocatedNum<F>,
  b: AllocatedNum<F>,
) -> Result<AllocatedBit, SynthesisError> {

To this"

pub fn alloc_num_equals<F: PrimeField, CS: ConstraintSystem>(
mut cs: CS,
a: &AllocatedNum,
b: &AllocatedNum,
) -> Result<AllocatedBit, SynthesisError> {


Thanks.

https://github.com/microsoft/Nova/blob/main/src/gadgets/utils.rs#:~:text=a%3A%20AllocatedNum%3CF,b%3A%20AllocatedNum%3CF%3E%2C

Is Nova quantum ready?

Quatum computing is seeing exponential development and it is conceivable that we will be able to run Shor's algorithm within 2030. That would break all convetional public key algorithms based on the hardness of prime factoring. It would also render all zk-SNARK-proofs compromised for forgery. Therefore switching to quantum secure cryptography is a must for serious application now even if the crack is some years away. Old proofs will be rendered entirely compromised and useless after that point. Therefore you would either need a system to upgrade and detrust old proofs, which would require recomputing all of them, or just start off quantum secure. The latter is definitely more realistic.

https://www.ncsc.gov.uk/whitepaper/preparing-for-quantum-safe-cryptography

removing iteration count parameter (num_steps) from verify function

Currently, "verify" methods of both RecursiveSNARK and CompressedSNARK take the number of steps as a parameter. Is there a way to hide it from the verifier? i.e. a way to remove the need for num_steps being fed into the hashers. Reason why such a modification may be needed is that how many times a step circuit is run may leak information. Do you think this can be done without breaking the soundness and safety of the proof system?

Load existing KZG setup parameters

The code currently produces powers of tau, but this is intended to be used only for testing purposes. Our code can use any existing KZG setup parameters--even those that were performed for univariate polynomial based schemes such as Plonk or Marlin or their variants.

The code will be added to the setup method in src/provider/hyperkzg.rs to open an existing file, parse them, and initialize ck.

details about scalar_mul?

As commented within code above scalar_mul:

/// A gadget for scalar multiplication, optimized to use incomplete addition law.
/// The optimization here is analogous to https://github.com/arkworks-rs/r1cs-std/blob/6d64f379a27011b3629cf4c9cb38b7b7b695d5a0/src/groups/curves/short_weierstrass/mod.rs#L295,
/// except we use complete addition law over affine coordinates instead of projective coordinates for the tail bits

I have three questions:

  1. diving into code, split index is approximately located at G::Base::NUM_BITS - 2, why?

  2. why do not use complete addition law over projective coordinates within which field inversion disappears as arkworks-rs/r1cs-std do?

  3. other point representation methods such as NAF or GLV would outperform the binary representation here?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.