diff --git a/Cargo.toml b/Cargo.toml index b135d3f..df38f6c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spartan" -version = "0.4.1" +version = "0.5.0" authors = ["Srinath Setty "] edition = "2018" description = "High-speed zkSNARKs without trusted setup" diff --git a/README.md b/README.md index e1862bd..ebc1008 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Spartan: High-speed zkSNARKs without trusted setup ![Rust](https://github.com/microsoft/Spartan/workflows/Rust/badge.svg) -[![](https://img.shields.io/crates/v/spartan.svg)]((https://crates.io/crates/curve25519-dalek)) +[![](https://img.shields.io/crates/v/spartan.svg)]((https://crates.io/crates/spartan)) Spartan is a high-speed zero-knowledge proof system, a cryptographic primitive that enables a prover to prove a mathematical statement to a verifier without revealing anything besides the validity of the statement. This repository provides `libspartan,` a Rust library that implements a zero-knowledge succinct non-interactive argument of knowledge (zkSNARK), which is a type of zero-knowledge proof system with short proofs and fast verification times. The details of the Spartan proof system are described in our [paper](https://eprint.iacr.org/2019/550) published at [CRYPTO 2020](https://crypto.iacr.org/2020/). The security of the Spartan variant implemented in this library is based on the discrete logarithm problem in the random oracle model. @@ -16,7 +16,7 @@ We now highlight Spartan's distinctive features. * **General-purpose:** Spartan produces proofs for arbitrary NP statements. `libspartan` supports NP statements expressed as rank-1 constraint satisfiability (R1CS) instances, a popular language for which there exists efficient transformations and compiler toolchains from high-level programs of interest. -* **Sub-linear verification costs and linear-time proving costs:** Spartan is the first transparent proof system with sub-linear verification costs for arbitrary NP statements (e.g., R1CS). Spartan also features a linear-time prover, a property that has remained elusive for nearly all zkSNARKs in the literature. +* **Sub-linear verification costs:** Spartan is the first transparent proof system with sub-linear verification costs for arbitrary NP statements (e.g., R1CS). * **Standardized security:** Spartan's security relies on the hardness of computing discrete logarithms (a standard cryptographic assumption) in the random oracle model. `libspartan` uses `ristretto255`, a prime-order group abstraction atop `curve25519` (a high-speed elliptic curve). We use [`curve25519-dalek`](https://docs.rs/curve25519-dalek) for arithmetic over `ristretto255`. diff --git a/profiler/nizk.rs b/profiler/nizk.rs index 98bf48c..00cf5c5 100644 --- a/profiler/nizk.rs +++ b/profiler/nizk.rs @@ -10,7 +10,7 @@ use merlin::Transcript; fn print(msg: &str) { let star = "* "; - println!("{:indent$}{}{}", "", star, msg.to_string(), indent = 2); + println!("{:indent$}{}{}", "", star, msg, indent = 2); } pub fn main() { diff --git a/profiler/snark.rs b/profiler/snark.rs index 9f91924..cc4862a 100644 --- a/profiler/snark.rs +++ b/profiler/snark.rs @@ -9,7 +9,7 @@ use merlin::Transcript; fn print(msg: &str) { let star = "* "; - println!("{:indent$}{}{}", "", star, msg.to_string(), indent = 2); + println!("{:indent$}{}{}", "", star, msg, indent = 2); } pub fn main() { diff --git a/src/lib.rs b/src/lib.rs index d909d44..fc90919 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -441,17 +441,14 @@ impl SNARK { Ar.append_to_transcript(b"Ar_claim", transcript); Br.append_to_transcript(b"Br_claim", transcript); Cr.append_to_transcript(b"Cr_claim", transcript); - assert!(self - .r1cs_eval_proof - .verify( - &comm.comm, - &rx, - &ry, - &self.inst_evals, - &gens.gens_r1cs_eval, - transcript - ) - .is_ok()); + self.r1cs_eval_proof.verify( + &comm.comm, + &rx, + &ry, + &self.inst_evals, + &gens.gens_r1cs_eval, + transcript, + )?; timer_eval_proof.stop(); timer_verify.stop(); Ok(()) diff --git a/src/nizk/bullet.rs b/src/nizk/bullet.rs index a81d281..3f8951a 100644 --- a/src/nizk/bullet.rs +++ b/src/nizk/bullet.rs @@ -231,7 +231,7 @@ impl BulletReductionProof { /// Panics if the lengths of \\(\mathbf{a}\\) and \\(\mathbf{b}\\) are not equal. pub fn inner_product(a: &[Scalar], b: &[Scalar]) -> Scalar { assert!( - !(a.len() != b.len()), + a.len() == b.len(), "inner_product(a,b): lengths of vectors do not match" ); let mut out = Scalar::zero(); diff --git a/src/r1csinstance.rs b/src/r1csinstance.rs index a011279..8e3abea 100644 --- a/src/r1csinstance.rs +++ b/src/r1csinstance.rs @@ -336,18 +336,13 @@ impl R1CSEvalProof { gens: &R1CSCommitmentGens, transcript: &mut Transcript, ) -> Result<(), ProofVerifyError> { - assert!(self - .proof - .verify( - &comm.comm, - rx, - ry, - &[evals.0, evals.1, evals.2], - &gens.gens, - transcript - ) - .is_ok()); - - Ok(()) + self.proof.verify( + &comm.comm, + rx, + ry, + &[evals.0, evals.1, evals.2], + &gens.gens, + transcript, + ) } } diff --git a/src/r1csproof.rs b/src/r1csproof.rs index c11cdcb..d57735f 100644 --- a/src/r1csproof.rs +++ b/src/r1csproof.rs @@ -382,18 +382,14 @@ impl R1CSProof { let (comm_Az_claim, comm_Bz_claim, comm_Cz_claim, comm_prod_Az_Bz_claims) = &self.claims_phase2; let (pok_Cz_claim, proof_prod) = &self.pok_claims_phase2; - assert!(pok_Cz_claim - .verify(&gens.gens_sc.gens_1, transcript, comm_Cz_claim) - .is_ok()); - assert!(proof_prod - .verify( - &gens.gens_sc.gens_1, - transcript, - comm_Az_claim, - comm_Bz_claim, - comm_prod_Az_Bz_claims - ) - .is_ok()); + pok_Cz_claim.verify(&gens.gens_sc.gens_1, transcript, comm_Cz_claim)?; + proof_prod.verify( + &gens.gens_sc.gens_1, + transcript, + comm_Az_claim, + comm_Bz_claim, + comm_prod_Az_Bz_claims, + )?; comm_Az_claim.append_to_transcript(b"comm_Az_claim", transcript); comm_Bz_claim.append_to_transcript(b"comm_Bz_claim", transcript); @@ -408,15 +404,12 @@ impl R1CSProof { .compress(); // verify proof that expected_claim_post_phase1 == claim_post_phase1 - assert!(self - .proof_eq_sc_phase1 - .verify( - &gens.gens_sc.gens_1, - transcript, - &expected_claim_post_phase1, - &comm_claim_post_phase1, - ) - .is_ok()); + self.proof_eq_sc_phase1.verify( + &gens.gens_sc.gens_1, + transcript, + &expected_claim_post_phase1, + &comm_claim_post_phase1, + )?; // derive three public challenges and then derive a joint claim let r_A = transcript.challenge_scalar(b"challenege_Az"); @@ -447,16 +440,13 @@ impl R1CSProof { )?; // verify Z(ry) proof against the initial commitment - assert!(self - .proof_eval_vars_at_ry - .verify( - &gens.gens_pc, - transcript, - &ry[1..].to_vec(), - &self.comm_vars_at_ry, - &self.comm_vars - ) - .is_ok()); + self.proof_eval_vars_at_ry.verify( + &gens.gens_pc, + transcript, + &ry[1..].to_vec(), + &self.comm_vars_at_ry, + &self.comm_vars, + )?; let poly_input_eval = { // constant term @@ -484,15 +474,12 @@ impl R1CSProof { let expected_claim_post_phase2 = ((r_A * eval_A_r + r_B * eval_B_r + r_C * eval_C_r) * comm_eval_Z_at_ry).compress(); // verify proof that expected_claim_post_phase1 == claim_post_phase1 - assert!(self - .proof_eq_sc_phase2 - .verify( - &gens.gens_sc.gens_1, - transcript, - &expected_claim_post_phase2, - &comm_claim_post_phase2, - ) - .is_ok()); + self.proof_eq_sc_phase2.verify( + &gens.gens_sc.gens_1, + transcript, + &expected_claim_post_phase2, + &comm_claim_post_phase2, + )?; Ok((rx, ry)) } diff --git a/src/sparse_mlpoly.rs b/src/sparse_mlpoly.rs index 690c438..df9e240 100644 --- a/src/sparse_mlpoly.rs +++ b/src/sparse_mlpoly.rs @@ -178,11 +178,8 @@ impl DerefsEvalProof { // decommit the joint polynomial at r_joint joint_claim_eval.append_to_transcript(b"joint_claim_eval", transcript); - assert!(proof - .verify_plain(gens, transcript, &r_joint, &joint_claim_eval, comm) - .is_ok()); - Ok(()) + proof.verify_plain(gens, transcript, &r_joint, &joint_claim_eval, comm) } // verify evaluations of both polynomials at r @@ -200,7 +197,7 @@ impl DerefsEvalProof { evals.extend(eval_col_ops_val_vec); evals.resize(evals.len().next_power_of_two(), Scalar::zero()); - assert!(DerefsEvalProof::verify_single( + DerefsEvalProof::verify_single( &self.proof_derefs, &comm.comm_ops_val, r, @@ -208,9 +205,6 @@ impl DerefsEvalProof { gens, transcript, ) - .is_ok()); - - Ok(()) } } @@ -910,17 +904,14 @@ impl HashLayerProof { // verify derefs at rand_ops let (eval_row_ops_val, eval_col_ops_val) = &self.eval_derefs; assert_eq!(eval_row_ops_val.len(), eval_col_ops_val.len()); - assert!(self - .proof_derefs - .verify( - rand_ops, - eval_row_ops_val, - eval_col_ops_val, - &gens.gens_derefs, - comm_derefs, - transcript - ) - .is_ok()); + self.proof_derefs.verify( + rand_ops, + eval_row_ops_val, + eval_col_ops_val, + &gens.gens_derefs, + comm_derefs, + transcript, + )?; // verify the decommitments used in evaluation sum-check let eval_val_vec = &self.eval_val; @@ -990,20 +981,17 @@ impl HashLayerProof { let mut r_joint_mem = challenges_mem; r_joint_mem.extend(rand_mem); joint_claim_eval_mem.append_to_transcript(b"joint_claim_eval_mem", transcript); - assert!(self - .proof_mem - .verify_plain( - &gens.gens_mem, - transcript, - &r_joint_mem, - &joint_claim_eval_mem, - &comm.comm_comb_mem - ) - .is_ok()); + self.proof_mem.verify_plain( + &gens.gens_mem, + transcript, + &r_joint_mem, + &joint_claim_eval_mem, + &comm.comm_comb_mem, + )?; // verify the claims from the product layer let (eval_ops_addr, eval_read_ts, eval_audit_ts) = &self.eval_row; - assert!(HashLayerProof::verify_helper( + HashLayerProof::verify_helper( &(rand_mem, rand_ops), claims_row, eval_row_ops_val, @@ -1013,11 +1001,10 @@ impl HashLayerProof { rx, r_hash, r_multiset_check, - ) - .is_ok()); + )?; let (eval_ops_addr, eval_read_ts, eval_audit_ts) = &self.eval_col; - assert!(HashLayerProof::verify_helper( + HashLayerProof::verify_helper( &(rand_mem, rand_ops), claims_col, eval_col_ops_val, @@ -1027,8 +1014,7 @@ impl HashLayerProof { ry, r_hash, r_multiset_check, - ) - .is_ok()); + )?; timer.stop(); Ok(()) @@ -1562,22 +1548,17 @@ impl SparseMatPolyEvalProof { // produce a random element from the transcript for hash function let r_mem_check = transcript.challenge_vector(b"challenge_r_hash", 2); - assert!(self - .poly_eval_network_proof - .verify( - comm, - &self.comm_derefs, - evals, - gens, - &rx_ext, - &ry_ext, - &(r_mem_check[0], r_mem_check[1]), - nz, - transcript, - ) - .is_ok()); - - Ok(()) + self.poly_eval_network_proof.verify( + comm, + &self.comm_derefs, + evals, + gens, + &rx_ext, + &ry_ext, + &(r_mem_check[0], r_mem_check[1]), + nz, + transcript, + ) } } diff --git a/src/sumcheck.rs b/src/sumcheck.rs index 5973a6f..a077c10 100644 --- a/src/sumcheck.rs +++ b/src/sumcheck.rs @@ -168,7 +168,9 @@ impl ZKSumcheckInstanceProof { ) .is_ok() }; - assert!(res); + if !res { + return Err(ProofVerifyError::InternalError); + } r.push(r_i); }