Skip to content

Commit

Permalink
Small refactors
Browse files Browse the repository at this point in the history
- remove unused/commented out functions
- revert to 128-bit limb hashing due to security concern
- make ScalarMulAccumulator take ownership of R1CS accumulator
- add ability to generate dummy input proof for circuit
- use sponge for hashing the NIVC instance due to problems with variable-sized hashing
- add test for `from_proof`
- comment out merge-related code
- ensure namespaces have unique names
- remove wrong mersenne prime parameters
- add emulatedbase tests
- add cycle fold circuit
- add inputize_hashed methods in allocated point for cyclefold circuit
  • Loading branch information
adr1anh committed Mar 4, 2024
1 parent aa1ef90 commit d59a0d1
Show file tree
Hide file tree
Showing 18 changed files with 504 additions and 324 deletions.
1 change: 1 addition & 0 deletions src/parafold/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::parafold::transcript::TranscriptConstants;
use crate::supernova::StepCircuit;
use crate::traits::CurveCycleEquipped;

#[allow(unused)]
pub fn synthesize_step<E, CS, SF>(
mut cs: CS,
ro_consts: &TranscriptConstants<E::Scalar>,
Expand Down
23 changes: 14 additions & 9 deletions src/parafold/cycle_fold/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use bellpepper_core::boolean::Boolean;
use bellpepper_core::{ConstraintSystem, SynthesisError, Variable};
use ff::PrimeField;

use crate::parafold::cycle_fold::gadgets::emulated::AllocatedBase;
use crate::parafold::cycle_fold::nifs::circuit::AllocatedSecondaryRelaxedR1CSInstance;
use crate::parafold::cycle_fold::{AllocatedPrimaryCommitment, NUM_IO_SECONDARY};
use crate::parafold::cycle_fold::nifs::NUM_IO_SECONDARY;
use crate::parafold::cycle_fold::AllocatedPrimaryCommitment;
use crate::parafold::transcript::circuit::AllocatedTranscript;
use crate::traits::CurveCycleEquipped;

Expand Down Expand Up @@ -33,6 +35,9 @@ impl<E: CurveCycleEquipped> AllocatedScalarMulAccumulator<E> {
where
CS: ConstraintSystem<E::Scalar>,
{
// Ensure the number of bits in the scalar matches fits.
assert!(x_bits.len() <= E::Scalar::NUM_BITS as usize);

let C = transcript.read_commitment_primary(cs.namespace(|| "transcript C"))?;

self.deferred.push(AllocatedScalarMulInstance {
Expand All @@ -45,6 +50,8 @@ impl<E: CurveCycleEquipped> AllocatedScalarMulAccumulator<E> {
Ok(C)
}

/// Consume a set of accumulated scalar multiplications, proving each instance by folding a proof
/// into the internal secondary curve accumulator.
pub fn finalize<CS>(
mut self,
mut cs: CS,
Expand All @@ -53,22 +60,20 @@ impl<E: CurveCycleEquipped> AllocatedScalarMulAccumulator<E> {
where
CS: ConstraintSystem<E::Scalar>,
{
for instance in self.deferred.drain(..) {
for (i, instance) in self.deferred.drain(..).enumerate() {
let X = instance.to_io(CS::one());

// TODO: In order to avoid computing unnecessary proofs, we can check
// - x = 0 => C = A
self
.acc
.fold(cs.namespace(|| "fold cf instance"), X, transcript)?;
self.acc.fold(
cs.namespace(|| format!("fold cf instance {i}")),
X,
transcript,
)?;
}

Ok(self.acc)
}

pub fn is_finalized(&self) -> bool {
self.deferred.is_empty()
}
}

#[derive(Debug, Clone)]
Expand Down
89 changes: 52 additions & 37 deletions src/parafold/cycle_fold/gadgets/ecc.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use bellpepper::gadgets::Assignment;
use bellpepper_core::boolean::{AllocatedBit, Boolean};
use bellpepper_core::num::AllocatedNum;

use bellpepper_core::SynthesisError::AssignmentMissing;
use bellpepper_core::{ConstraintSystem, SynthesisError};
use ff::{Field, PrimeField};
use neptune::circuit2::Elt;
use neptune::circuit2::{Elt, PoseidonCircuit2};
use neptune::generic_array::typenum::U2;
use neptune::poseidon::PoseidonConstants;

use crate::gadgets::utils::{
alloc_num_equals, alloc_one, alloc_zero, conditionally_select, conditionally_select2,
Expand Down Expand Up @@ -78,6 +82,53 @@ impl<G: Group> AllocatedPoint<G> {
commitment
}

pub fn alloc_hashed_input<CS>(
mut cs: CS,
coords: (G::Base, G::Base, bool),
) -> Result<Self, SynthesisError>
where
CS: ConstraintSystem<G::Base>,
{
let point = Self::alloc_unchecked(cs.namespace(|| "alloc"), coords);
point.check_on_curve(cs.namespace(|| "check on curve"))?;
point.inputize_hashed(cs.namespace(|| "inputize"))?;
Ok(point)
}

/// Inputize a point by computing H(x,y), or 0 if `is_infinity = true`.
pub fn inputize_hashed<CS>(&self, mut cs: CS) -> Result<(), SynthesisError>
where
CS: ConstraintSystem<G::Base>,
{
let constants = PoseidonConstants::<G::Base, U2>::new();
let hash = PoseidonCircuit2::new(
vec![
Elt::Allocated(self.x.clone()),
Elt::Allocated(self.y.clone()),
],
&constants,
)
.hash_to_allocated(cs.namespace(|| "hash"))?;

let hash_final = AllocatedNum::alloc(cs.namespace(|| "alloc hash"), || {
let is_infinity = self.is_infinity.get_value().ok_or(AssignmentMissing)?;
if is_infinity == G::Base::ONE {
Ok(G::Base::ZERO)
} else {
hash.get_value().ok_or(AssignmentMissing)
}
})?;

// hash_final = (1-is_infinity)hash
cs.enforce(
|| "select hash",
|lc| lc + CS::one() - self.is_infinity.get_variable(),
|lc| lc + hash.get_variable(),
|lc| lc + hash_final.get_variable(),
);
hash_final.inputize(cs.namespace(|| "inputize"))
}

/// Allocates a new point on the curve using coordinates provided by `coords`.
/// If coords = None, it allocates the default infinity point
pub fn alloc_unchecked<CS>(mut cs: CS, coords: (G::Base, G::Base, bool)) -> Self
Expand Down Expand Up @@ -166,17 +217,6 @@ impl<G: Group> AllocatedPoint<G> {
}
}

/// Returns coordinates associated with the point.
pub const fn get_coordinates(
&self,
) -> (
&AllocatedNum<G::Base>,
&AllocatedNum<G::Base>,
&AllocatedNum<G::Base>,
) {
(&self.x, &self.y, &self.is_infinity)
}

/// Negates the provided point
pub fn negate<CS>(&self, mut cs: CS) -> Result<Self, SynthesisError>
where
Expand Down Expand Up @@ -669,26 +709,6 @@ pub struct AllocatedPointNonInfinity<G: Group> {
}

impl<G: Group> AllocatedPointNonInfinity<G> {
/// Creates a new `AllocatedPointNonInfinity` from the specified coordinates
pub fn new(x: AllocatedNum<G::Base>, y: AllocatedNum<G::Base>) -> Self {
Self { x, y }
}

/// Allocates a new point on the curve using coordinates provided by `coords`.
pub fn alloc<CS: ConstraintSystem<G::Base>>(
mut cs: CS,
coords: Option<(G::Base, G::Base)>,
) -> Result<Self, SynthesisError> {
let x = AllocatedNum::alloc(cs.namespace(|| "x"), || {
coords.map_or(Err(SynthesisError::AssignmentMissing), |c| Ok(c.0))
})?;
let y = AllocatedNum::alloc(cs.namespace(|| "y"), || {
coords.map_or(Err(SynthesisError::AssignmentMissing), |c| Ok(c.1))
})?;

Ok(Self { x, y })
}

/// Turns an `AllocatedPoint` into an `AllocatedPointNonInfinity` (assumes it is not infinity)
pub fn from_allocated_point(p: &AllocatedPoint<G>) -> Self {
Self {
Expand All @@ -706,11 +726,6 @@ impl<G: Group> AllocatedPointNonInfinity<G> {
}
}

/// Returns coordinates associated with the point.
pub const fn get_coordinates(&self) -> (&AllocatedNum<G::Base>, &AllocatedNum<G::Base>) {
(&self.x, &self.y)
}

/// Add two points assuming self != +/- other
pub fn add_incomplete<CS>(&self, mut cs: CS, other: &Self) -> Result<Self, SynthesisError>
where
Expand Down
Loading

0 comments on commit d59a0d1

Please sign in to comment.