Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Refactor/zkey improves #282

Merged
merged 4 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ ark-bn254 = "0.4.0"
ark-ec = { version = "0.4.2", default-features = false }
ark-ff = "0.4.2"
ark-poly = "0.4.2"
ark-relations = { version = "0.4.0", default-features = false }
ark-serialize = { version = "0.4", features = ["derive", "std"] }
ark-std = { version = "0.4.0", features = ["std"] }
bincode = "1.3.3"
Expand Down
1 change: 0 additions & 1 deletion co-circom/circom-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ ark-bn254 = { workspace = true }
ark-ec = { workspace = true }
ark-ff = { workspace = true }
ark-poly = { workspace = true }
ark-relations = { workspace = true }
ark-serialize = { workspace = true }
ark-std = { workspace = true }
byteorder = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions co-circom/circom-types/src/groth16/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod zkey;
pub use proof::Groth16Proof;
pub use public_input::JsonPublicInput;
pub use verification_key::JsonVerificationKey;
pub use zkey::ConstraintMatrix;
pub use zkey::ZKey;

#[cfg(test)]
Expand Down
216 changes: 75 additions & 141 deletions co-circom/circom-types/src/groth16/zkey.rs

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions co-circom/co-circom-snarks/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use mpc_core::protocols::{
use rand::{distributions::Standard, prelude::Distribution, CryptoRng, Rng, SeedableRng};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::error::Error;

/// This type represents the serialized version of a Rep3 witness. Its share can be either additive or replicated, and in both cases also compressed.
#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -452,6 +453,44 @@ impl<F: PrimeField> SharedWitness<F, ShamirPrimeFieldShare<F>> {
}
}

/// The error type for the verification of a Circom proof.
///
/// If the verification failed because the proof is Invalid, the method
/// will return the [VerificationError::InvalidProof] variant. If the
/// underlying implementation encounters an error, the method
/// will wrap that error in the [VerificationError::Malformed] variant.
#[derive(Debug)]
pub enum VerificationError {
/// Indicates that the proof verification failed
InvalidProof,
/// Wraps an underlying error (e.g., malformed verification key)
Malformed(eyre::Report),
}

impl From<eyre::Report> for VerificationError {
fn from(error: eyre::Report) -> Self {
VerificationError::Malformed(error)
}
}

impl std::error::Error for VerificationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
VerificationError::Malformed(source) => Some(source.as_ref()),
VerificationError::InvalidProof => None,
}
}
}

impl std::fmt::Display for VerificationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
VerificationError::InvalidProof => writeln!(f, "proof is invalid"),
VerificationError::Malformed(error) => writeln!(f, "cannot verify proof: {error}"),
}
}
}

/// Gathers utility methods for proving coSNARKs.
pub mod utils {
use ark_ff::{FftField, LegendreSymbol, PrimeField};
Expand Down
26 changes: 14 additions & 12 deletions co-circom/co-circom/src/bin/co-circom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ use co_circom::VerifyCli;
use co_circom::VerifyConfig;
use co_circom::{file_utils, MPCCurve, MPCProtocol, ProofSystem, SeedRng};
use co_circom_snarks::{
SerializeableSharedRep3Input, SerializeableSharedRep3Witness, SharedWitness,
SerializeableSharedRep3Input, SerializeableSharedRep3Witness, SharedWitness, VerificationError,
};
use co_groth16::Groth16;
use co_groth16::{Rep3CoGroth16, ShamirCoGroth16};
use co_plonk::Rep3CoPlonk;
use co_plonk::{Plonk, ShamirCoPlonk};
use color_eyre::eyre::{eyre, Context, ContextCompat};
use color_eyre::eyre::{self, eyre, Context, ContextCompat};
use mpc_core::protocols::{
bridges::network::RepToShamirNetwork,
rep3::network::Rep3MpcNet,
Expand Down Expand Up @@ -659,8 +659,7 @@ where

// The actual verifier
let start = Instant::now();
let res = Groth16::<P>::verify(&vk, &proof, &public_inputs)
.context("while verifying proof")?;
let res = Groth16::<P>::verify(&vk, &proof, &public_inputs);
let duration_ms = start.elapsed().as_micros() as f64 / 1000.;
tracing::info!("Proof verification took {} ms", duration_ms);
res
Expand All @@ -674,20 +673,23 @@ where

// The actual verifier
let start = Instant::now();
let res =
Plonk::<P>::verify(&vk, &proof, &public_inputs).context("while verifying proof")?;
let res = Plonk::<P>::verify(&vk, &proof, &public_inputs);
let duration_ms = start.elapsed().as_micros() as f64 / 1000.;
tracing::info!("Proof verification took {} ms", duration_ms);
res
}
};

if res {
tracing::info!("Proof verified successfully");
Ok(ExitCode::SUCCESS)
} else {
tracing::error!("Proof verification failed");
Ok(ExitCode::FAILURE)
match res {
Ok(_) => {
tracing::info!("Proof verified successfully");
Ok(ExitCode::SUCCESS)
}
Err(VerificationError::InvalidProof) => {
tracing::error!("Proof verification failed");
Ok(ExitCode::FAILURE)
}
Err(VerificationError::Malformed(err)) => eyre::bail!(err),
}
}

Expand Down
1 change: 0 additions & 1 deletion co-circom/co-groth16/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ ark-groth16 = { version = "=0.4.0", default-features = false, features = [
"parallel",
], optional = true }
ark-poly = { workspace = true }
ark-relations = { workspace = true }
ark-serialize = { workspace = true }
circom-types = { version = "0.6.0", path = "../circom-types" }
co-circom-snarks = { version = "0.2.0", path = "../co-circom-snarks" }
Expand Down
45 changes: 21 additions & 24 deletions co-circom/co-groth16/src/groth16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ use ark_ec::scalar_mul::variable_base::VariableBaseMSM;
use ark_ec::{AffineRepr, CurveGroup};
use ark_ff::{FftField, PrimeField};
use ark_poly::{EvaluationDomain, GeneralEvaluationDomain};
use ark_relations::r1cs::{ConstraintMatrices, Matrix, SynthesisError};
use circom_types::groth16::{Groth16Proof, ZKey};
use circom_types::groth16::{ConstraintMatrix, Groth16Proof, ZKey};
use circom_types::traits::{CircomArkworksPairingBridge, CircomArkworksPrimeFieldBridge};
use co_circom_snarks::SharedWitness;
use eyre::Result;
Expand Down Expand Up @@ -116,19 +115,17 @@ where
let id = self.driver.get_party_id();
tracing::info!("Party {}: starting proof generation..", id);
let start = Instant::now();
let matrices = &zkey.matrices;
let num_inputs = matrices.num_instance_variables;
let num_constraints = matrices.num_constraints;
let public_inputs = Arc::new(private_witness.public_inputs);
if public_inputs.len() != zkey.n_public + 1 {
eyre::bail!(
"amount of public inputs do not match with provided zkey! Expected {}, but got {}",
zkey.n_public + 1,
public_inputs.len()
)
}

let private_witness = Arc::new(private_witness.witness);
let h = self.witness_map_from_matrices(
zkey.pow,
matrices,
num_constraints,
num_inputs,
&public_inputs,
&private_witness,
)?;
let h = self.witness_map_from_matrices(&zkey, &public_inputs, &private_witness)?;
let (r, s) = (self.driver.rand()?, self.driver.rand()?);

let proof = self.create_proof_with_assignment(
Expand All @@ -148,7 +145,7 @@ where
fn evaluate_constraint(
party_id: T::PartyID,
domain_size: usize,
matrix: &Matrix<P::ScalarField>,
matrix: &ConstraintMatrix<P::ScalarField>,
public_inputs: &[P::ScalarField],
private_witness: &[T::ArithmeticShare],
) -> Vec<T::ArithmeticShare> {
Expand All @@ -164,16 +161,16 @@ where
#[instrument(level = "debug", name = "witness map from matrices", skip_all)]
fn witness_map_from_matrices(
&mut self,
power: usize,
matrices: &ConstraintMatrices<P::ScalarField>,
num_constraints: usize,
num_inputs: usize,
zkey: &ZKey<P>,
public_inputs: &[P::ScalarField],
private_witness: &[T::ArithmeticShare],
) -> Result<Vec<P::ScalarField>> {
let num_constraints = zkey.num_constraints;
let num_inputs = zkey.n_public + 1;
let power = zkey.pow;
let mut domain =
GeneralEvaluationDomain::<P::ScalarField>::new(num_constraints + num_inputs)
.ok_or(SynthesisError::PolynomialDegreeTooLarge)?;
.ok_or(eyre::eyre!("Polynomial Degree too large"))?;
let domain_size = domain.size();
let party_id = self.driver.get_party_id();
let eval_constraint_span =
Expand All @@ -198,7 +195,7 @@ where
let mut result = Self::evaluate_constraint(
party_id,
domain_size,
&matrices.a,
&zkey.a_matrix,
public_inputs,
private_witness,
);
Expand All @@ -214,7 +211,7 @@ where
let result = Self::evaluate_constraint(
party_id,
domain_size,
&matrices.b,
&zkey.b_matrix,
public_inputs,
private_witness,
);
Expand Down Expand Up @@ -351,10 +348,10 @@ where
let aux_assignment2 = Arc::clone(&aux_assignment);
let aux_assignment3 = Arc::clone(&aux_assignment);
let aux_assignment4 = Arc::clone(&aux_assignment);
let alpha_g1 = zkey.vk.alpha_g1;
let alpha_g1 = zkey.alpha_g1;
let beta_g1 = zkey.beta_g1;
let beta_g2 = zkey.vk.beta_g2;
let delta_g2 = zkey.vk.delta_g2.into_group();
let beta_g2 = zkey.beta_g2;
let delta_g2 = zkey.delta_g2.into_group();

rayon::spawn(move || {
let compute_a =
Expand Down
36 changes: 10 additions & 26 deletions co-circom/co-groth16/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ mod tests {
Groth16::<Bn254>::plain_prove(zkey, witness).expect("proof generation works");
let ser_proof = serde_json::to_string(&proof).unwrap();
let der_proof = serde_json::from_str::<Groth16Proof<Bn254>>(&ser_proof).unwrap();
let verified =
Groth16::verify(&vk, &der_proof, &public_input[1..]).expect("can verify");
assert!(verified);
Groth16::verify(&vk, &der_proof, &public_input[1..]).expect("can verify");
}
}

Expand All @@ -73,9 +71,8 @@ mod tests {
let public_input =
serde_json::from_str::<JsonPublicInput<ark_bn254::Fr>>(public_string).unwrap();
let proof = serde_json::from_str::<Groth16Proof<Bn254>>(&proof_string).unwrap();
let verified =
Groth16::<Bn254>::verify(&vk, &proof, &public_input.values).expect("can verify");
assert!(verified)

Groth16::<Bn254>::verify(&vk, &proof, &public_input.values).expect("can verify");
}

#[test]
Expand All @@ -100,9 +97,7 @@ mod tests {
Groth16::<Bn254>::plain_prove(zkey, witness).expect("proof generation works");
let ser_proof = serde_json::to_string(&proof).unwrap();
let der_proof = serde_json::from_str::<Groth16Proof<Bn254>>(&ser_proof).unwrap();
let verified =
Groth16::verify(&vk, &der_proof, &public_input[1..]).expect("can verify");
assert!(verified);
Groth16::verify(&vk, &der_proof, &public_input[1..]).expect("can verify");
}
}

Expand All @@ -121,8 +116,7 @@ mod tests {
let public_input =
serde_json::from_str::<JsonPublicInput<ark_bn254::Fr>>(public_string).unwrap();
let proof = serde_json::from_str::<Groth16Proof<Bn254>>(&proof_string).unwrap();
let verified = Groth16::verify(&vk, &proof, &public_input.values).expect("can verify");
assert!(verified)
Groth16::verify(&vk, &proof, &public_input.values).expect("can verify");
}

#[test]
Expand All @@ -140,9 +134,7 @@ mod tests {
let public_input =
serde_json::from_str::<JsonPublicInput<ark_bls12_381::Fr>>(public_string).unwrap();
let proof = serde_json::from_str::<Groth16Proof<Bls12_381>>(&proof_string).unwrap();
let verified =
Groth16::<Bls12_381>::verify(&vk, &proof, &public_input.values).expect("can verify");
assert!(verified)
Groth16::<Bls12_381>::verify(&vk, &proof, &public_input.values).expect("can verify");
}

#[test]
Expand All @@ -169,14 +161,10 @@ mod tests {

let proof =
Groth16::<Bls12_381>::plain_prove(zkey, witness).expect("proof generation works");
let verified =
Groth16::<Bls12_381>::verify(&vk, &proof, &public_input[1..]).expect("can verify");
assert!(verified);
Groth16::<Bls12_381>::verify(&vk, &proof, &public_input[1..]).expect("can verify");
let ser_proof = serde_json::to_string(&proof).unwrap();
let der_proof = serde_json::from_str::<Groth16Proof<Bls12_381>>(&ser_proof).unwrap();
let verified = Groth16::<Bls12_381>::verify(&vk, &der_proof, &public_input[1..])
.expect("can verify");
assert!(verified)
Groth16::<Bls12_381>::verify(&vk, &der_proof, &public_input[1..]).expect("can verify");
}
}

Expand All @@ -201,14 +189,10 @@ mod tests {

let proof =
Groth16::<Bn254>::plain_prove(zkey, witness).expect("proof generation works");
let verified =
Groth16::<Bn254>::verify(&vk, &proof, &public_input[1..]).expect("can verify");
assert!(verified);
Groth16::<Bn254>::verify(&vk, &proof, &public_input[1..]).expect("can verify");
let ser_proof = serde_json::to_string(&proof).unwrap();
let der_proof = serde_json::from_str::<Groth16Proof<Bn254>>(&ser_proof).unwrap();
let verified =
Groth16::<Bn254>::verify(&vk, &der_proof, &public_input[1..]).expect("can verify");
assert!(verified)
Groth16::<Bn254>::verify(&vk, &der_proof, &public_input[1..]).expect("can verify");
}
}
}
11 changes: 9 additions & 2 deletions co-circom/co-groth16/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use circom_types::groth16::{Groth16Proof, JsonVerificationKey};
use circom_types::traits::{CircomArkworksPairingBridge, CircomArkworksPrimeFieldBridge};

use ark_groth16::Groth16 as ArkworksGroth16;
use co_circom_snarks::VerificationError;

impl<P: Pairing> Groth16<P>
where
Expand All @@ -24,7 +25,7 @@ where
vk: &JsonVerificationKey<P>,
proof: &Groth16Proof<P>,
public_inputs: &[P::ScalarField],
) -> Result<bool, ark_relations::r1cs::SynthesisError> {
) -> Result<(), VerificationError> {
let vk = VerifyingKey::<P> {
alpha_g1: vk.alpha_1,
beta_g2: vk.beta_2,
Expand All @@ -39,6 +40,12 @@ where
};

let vk = ark_groth16::prepare_verifying_key(&vk);
ArkworksGroth16::<P>::verify_proof(&vk, &proof, public_inputs)
let proof_valid = ArkworksGroth16::<P>::verify_proof(&vk, &proof, public_inputs)
.map_err(eyre::Report::from)?;
if proof_valid {
Ok(())
} else {
Err(VerificationError::InvalidProof)
}
}
}
6 changes: 2 additions & 4 deletions co-circom/co-plonk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,7 @@ pub mod tests {
.unwrap();

let proof = Plonk::<Bn254>::plain_prove(zkey, witness).unwrap();
let result = Plonk::<Bn254>::verify(&vk, &proof, &public_input.values).unwrap();
assert!(result);
Plonk::<Bn254>::verify(&vk, &proof, &public_input.values).unwrap();
}
Ok(())
}
Expand Down Expand Up @@ -337,8 +336,7 @@ pub mod tests {
let mut proof_bytes = vec![];
serde_json::to_writer(&mut proof_bytes, &proof).unwrap();
let proof = serde_json::from_reader(proof_bytes.as_slice()).unwrap();
let result = Plonk::<Bn254>::verify(&vk, &proof, &public_inputs.values).unwrap();
assert!(result)
Plonk::<Bn254>::verify(&vk, &proof, &public_inputs.values).unwrap();
}
}
}
Loading