Skip to content

Commit

Permalink
feat(circuit): implement ecc point compression of the PCD secondary c…
Browse files Browse the repository at this point in the history
…urve (#19)
  • Loading branch information
RequiemOfSoul committed Jun 13, 2024
1 parent 87d9bfa commit 94080e8
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 40 deletions.
18 changes: 18 additions & 0 deletions src/gadgets/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,24 @@ where
.inputize(cs.namespace(|| "Input point.is_infinity"))?;
Ok(())
}

/// Make the point to compressed io
pub fn compressed_inputize<CS: ConstraintSystem<G::Base>>(
&self,
mut cs: CS,
ecc_parity_manager: &mut Vec<Boolean>,
) -> Result<(), SynthesisError> {
self.x.inputize(cs.namespace(|| "Input point.x"))?;
ecc_parity_manager.push(
self
.y
.to_bits_le_strict(cs.namespace(|| "calc bits"))?
.first()
.unwrap()
.clone(),
);
Ok(())
}
}

#[derive(Clone)]
Expand Down
32 changes: 32 additions & 0 deletions src/gadgets/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,38 @@ where
Ok(num)
}

pub fn from_le_bits_to_num<Scalar, CS>(
mut cs: CS,
bits: &[Boolean],
) -> Result<AllocatedNum<Scalar>, SynthesisError>
where
Scalar: PrimeField + PrimeFieldBits,
CS: ConstraintSystem<Scalar>,
{
// We loop over the input bits and construct the constraint
// and the field element that corresponds to the result
let mut lc = LinearCombination::zero();
let mut coeff = Scalar::ONE;
let mut fe = Some(Scalar::ZERO);
for bit in bits.iter() {
lc = lc + &bit.lc(CS::one(), coeff);
fe = bit.get_value().map(|val| {
if val {
fe.unwrap() + coeff
} else {
fe.unwrap()
}
});
coeff = coeff.double();
}
let num = AllocatedNum::alloc(cs.namespace(|| "Field element"), || {
fe.ok_or(SynthesisError::AssignmentMissing)
})?;
lc = lc - num.get_variable();
cs.enforce(|| "compute number from bits", |lc| lc, |lc| lc, |_| lc);
Ok(num)
}

/// Allocate a variable that is set to zero
pub fn alloc_zero<F: PrimeField, CS: ConstraintSystem<F>>(
mut cs: CS,
Expand Down
1 change: 0 additions & 1 deletion src/nimfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub mod ccs;
pub mod multifolding;
pub mod pcd_aux_circuit;
pub mod pcd_circuit;
pub mod pcd_proof;

pub mod espresso;
pub mod util;
2 changes: 0 additions & 2 deletions src/nimfs/multifolding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,6 @@ impl<C: Group> MultiFolding<C> {
new_instances: &[CCCS<C>],
proof: Proof<C>,
) -> LCCCS<C> {
// TODO appends to transcript

assert!(!running_instances.is_empty());
assert!(!new_instances.is_empty());

Expand Down
23 changes: 19 additions & 4 deletions src/nimfs/pcd_aux_circuit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::compute_digest;
use crate::gadgets::cccs::{AllocatedCCCSSecondPart, AllocatedLCCCSSecondPart};
use crate::gadgets::utils::from_le_bits_to_num;
use crate::nimfs::ccs::cccs::CCCS;
use crate::nimfs::ccs::lcccs::LCCCS;
use crate::r1cs::R1CSShape;
Expand Down Expand Up @@ -133,16 +134,30 @@ impl<G: Group> NovaAuxiliarySecondCircuit<G> {
&rho,
)?;

// TODO: compress ecc point to x0, x1, x2, ... , ys_parity(the bit that expresses the parity of all y encode to element)
// public input
let mut ecc_parity_container = Vec::new();
rho.inputize(cs.namespace(|| "pub rho"))?;
for (i, x) in lcccs.into_iter().enumerate() {
x.C.inputize(cs.namespace(|| format!("{i}th lcccs")))?;
let mut cs = cs.namespace(|| format!("{i}th lcccs"));
x.C.check_on_curve(cs.namespace(|| "check C on curve"))?;
x.C
.compressed_inputize(cs.namespace(|| "input C"), &mut ecc_parity_container)?;
}
for (i, x) in cccs.into_iter().enumerate() {
x.C.inputize(cs.namespace(|| format!("{i}th cccs")))?;
let mut cs = cs.namespace(|| format!("{i}th cccs"));
x.C.check_on_curve(cs.namespace(|| "check C on curve"))?;
x.C
.compressed_inputize(cs.namespace(|| "input C"), &mut ecc_parity_container)?;
}
new_lcccs.C.inputize(cs.namespace(|| "pub new lcccs"))?;
new_lcccs
.C
.compressed_inputize(cs.namespace(|| "pub new lcccs"), &mut ecc_parity_container)?;

let ecc_compression_num = from_le_bits_to_num(
cs.namespace(|| "alloc ecc_compression_num"),
&ecc_parity_container,
)?;
ecc_compression_num.inputize(cs.namespace(|| "pub ecc_compression_num"))?;

Ok(())
}
Expand Down
1 change: 0 additions & 1 deletion src/nimfs/pcd_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,6 @@ where
) -> Result<AllocatedRelaxedR1CSInstance<G>, SynthesisError> {
assert!(!U.is_empty());
// Compute r
let _num_for_ro = 1 + 2 * (3 + 3 + 1 + 2 * self.params.n_limbs);
let mut ro = G::ROCircuit::new(self.ro_consts.clone(), 0);
ro.absorb(params);
for (i, U) in U.iter().enumerate() {
Expand Down
19 changes: 0 additions & 19 deletions src/nimfs/pcd_proof.rs

This file was deleted.

12 changes: 6 additions & 6 deletions src/pcd_compressed_snark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ where
pub(crate) ck_secondary: CommitmentKey<G2>,
pub(crate) primary_circuit_params: PCDUnitParams<G1, ARITY, R>,
pub(crate) secondary_circuit_params: NovaAuxiliaryParams<G2>,
// digest: G1::Scalar, // digest of everything else with this field set to G1::Scalar::ZERO
pub(crate) _p_c: PhantomData<SC>,
}

Expand All @@ -59,7 +58,7 @@ where
let _ = aux_circuit_setup.synthesize(&mut cs_aux_helper);
let (aux_r1cs_shape, ck_secondary) = cs_aux_helper.r1cs_shape();

let secondary_circuit_params = NovaAuxiliaryParams::new(aux_r1cs_shape, 6 * R + 4);
let secondary_circuit_params = NovaAuxiliaryParams::new(aux_r1cs_shape, R * 2 + 3);

// find eligible s and s_prime for satisfy PCD primary circuit
let (mut s, mut s_prime) = (16, 16);
Expand Down Expand Up @@ -180,6 +179,7 @@ where
digest: G1::Scalar,
vk_primary: S1::VerifierKey,
vk_secondary: S2::VerifierKey,
secondary_io_num: usize,
}

/// A SNARK that proves the knowledge of a valid `RecursiveSNARK`
Expand Down Expand Up @@ -235,6 +235,7 @@ where
digest: pp.primary_circuit_params.digest,
vk_primary,
vk_secondary,
secondary_io_num: pp.secondary_circuit_params.io_num,
};

Ok((pk, vk))
Expand Down Expand Up @@ -292,9 +293,9 @@ where
z0_primary: Vec<G1::Scalar>,
) -> Result<Vec<G1::Scalar>, NovaError> {
// check if the instances have two public outputs
if self.r_u_primary.x.len() != 1
|| self.r_U_primary.x.len() != 1
|| self.r_U_secondary.X.len() != 6 * R + 4
if self.r_u_primary.x.len() != ARITY
|| self.r_U_primary.x.len() != ARITY
|| self.r_U_secondary.X.len() != vk.secondary_io_num
{
return Err(NovaError::InvalidInputLength);
}
Expand Down Expand Up @@ -393,7 +394,6 @@ mod test {
let default_relaxed_r1cs_witness =
RelaxedR1CSWitness::<G2>::default(&pp.secondary_circuit_params.r1cs_shape);

println!("Creating PCD node1");
let node_1 = PCDNode::<G1, G2, IO_NUM, R>::new(
vec![default_lcccs.clone(), default_lcccs],
vec![default_cccs.clone(), default_cccs],
Expand Down
5 changes: 4 additions & 1 deletion src/pcd_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,10 @@ where
W: &RelaxedR1CSWitness<G2>,
) -> Result<Vec<G1::Scalar>, NovaError> {
println!("================================PCD verify===================================");
if U.X.len() != 6 * R + 4 && lcccs.x.len() != 1 && cccs.x.len() != 1 {
if U.X.len() != pp.secondary_circuit_params.io_num
|| lcccs.x.len() != ARITY
|| cccs.x.len() != ARITY
{
return Err(NovaError::ProofVerifyError);
}

Expand Down
7 changes: 1 addition & 6 deletions src/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use crate::{
use core::{cmp::max, marker::PhantomData};
use ff::Field;

use crate::nimfs::ccs::ccs::CCS;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -152,7 +151,7 @@ impl<G: Group> R1CSShape<G> {
pub(crate) fn check_regular_shape(&self) {
assert_eq!(self.num_cons.next_power_of_two(), self.num_cons);
assert_eq!(self.num_vars.next_power_of_two(), self.num_vars);
assert_eq!(self.num_io.next_power_of_two(), self.num_io);
// assert_eq!(self.num_io.next_power_of_two(), self.num_io);
assert!(self.num_io < self.num_vars);
}

Expand Down Expand Up @@ -422,10 +421,6 @@ impl<G: Group> R1CSShape<G> {
C: C_padded,
}
}

pub fn to_cccs(&self) -> CCS<G> {
todo!()
}
}

impl<G: Group> R1CSWitness<G> {
Expand Down

0 comments on commit 94080e8

Please sign in to comment.