Skip to content

Commit

Permalink
Working merge
Browse files Browse the repository at this point in the history
  • Loading branch information
adr1anh committed Mar 7, 2024
1 parent 396bbe5 commit 3e45ac5
Show file tree
Hide file tree
Showing 17 changed files with 1,121 additions and 1,300 deletions.
91 changes: 46 additions & 45 deletions src/parafold/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,68 @@
use bellpepper_core::{ConstraintSystem, SynthesisError};

use crate::parafold::nivc::circuit::AllocatedNIVCState;
use crate::parafold::nivc::{NIVCUpdateProof, NIVCIO};
use crate::parafold::nivc::{NIVCCircuitInput, NIVCMergeProof, NIVCIO};
use crate::parafold::transcript::TranscriptConstants;
use crate::supernova::StepCircuit;
use crate::traits::CurveCycleEquipped;

pub fn synthesize_step<E, CS, SF>(
mut cs: CS,
ro_consts: &TranscriptConstants<E::Scalar>,
proof: NIVCUpdateProof<E>,
input: &NIVCCircuitInput<E>,
ro_consts: TranscriptConstants<E::Scalar>,
step_circuit: &SF,
) -> Result<(Option<NIVCIO<E>>, AllocatedNIVCState<E>), SynthesisError>
) -> Result<Option<NIVCIO<E>>, SynthesisError>
where
E: CurveCycleEquipped,
CS: ConstraintSystem<E::Scalar>,
SF: StepCircuit<E::Scalar>,
{
// Fold proof for previous state
let (mut state, transcript_state) =
AllocatedNIVCState::from_proof(cs.namespace(|| "verify self"), ro_consts, proof)?;
let mut state = AllocatedNIVCState::init(cs.namespace(|| "alloc state"), ro_consts, input)?;

let io = state.update_io(cs.namespace(|| "step"), step_circuit)?;

state.inputize(cs.namespace(|| "inputize state"))?;
transcript_state.inputize(cs.namespace(|| "inputize transcript"))?;

Ok((io, state))
Ok(io)
}

// /// Circuit
// pub fn synthesize_merge<E, CS>(
// mut cs: CS,
// ro_consts: &TranscriptConstants<E::Scalar>,
// proof_L: NIVCUpdateProof<E>,
// proof_R: NIVCUpdateProof<E>,
// proof_merge: NIVCMergeProof<E>,
// ) -> Result<NIVCIO<E>, SynthesisError>
// where
// E: CurveCycleEquipped,
// CS: ConstraintSystem<E::Scalar>,
// {
// // Verify L
// let (self_L, transcript_L) =
// AllocatedNIVCState::from_proof(cs.namespace(|| "verify proof_L"), ro_consts, proof_L)?;
// // Verify R
// let (self_R, transcript_R) =
// AllocatedNIVCState::from_proof(cs.namespace(|| "verify proof_R"), ro_consts, proof_R)?;
// // Merge transcripts
// let mut transcript = AllocatedTranscript::merge(transcript_L, transcript_R);
//
// // Merge states
// let (state, io_native) = AllocatedNIVCState::merge(
// cs.namespace(|| "merge"),
// self_L,
// self_R,
// ro_consts,
// proof_merge,
// &mut transcript,
// )?;
//
// transcript.inputize(cs.namespace(|| "inputize transcript"))?;
// state.inputize(cs.namespace(|| "inputize state"))?;
//
// Ok(io_native)
// }
///Circuit
#[allow(unused)]
pub fn synthesize_merge<E, CS>(
mut cs: CS,
input_L: &NIVCCircuitInput<E>,
input_R: &NIVCCircuitInput<E>,
merge_proof: NIVCMergeProof<E>,
ro_consts: TranscriptConstants<E::Scalar>,
) -> Result<Option<NIVCIO<E>>, SynthesisError>
where
E: CurveCycleEquipped,
CS: ConstraintSystem<E::Scalar>,
{
// Verify L
let mut state_L = AllocatedNIVCState::init(
cs.namespace(|| "alloc state_L"),
ro_consts.clone(),
&input_L,
)?;

// Verify L
let mut state_R = AllocatedNIVCState::init(
cs.namespace(|| "alloc state_R"),
ro_consts.clone(),
&input_R,
)?;

// Merge states
let (state, io_native) = AllocatedNIVCState::merge(
cs.namespace(|| "merge"),
state_L,
state_R,
merge_proof,
ro_consts,
)?;

state.inputize(cs.namespace(|| "inputize state"))?;

Ok(io_native)
}
28 changes: 15 additions & 13 deletions src/parafold/cycle_fold/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
use bellpepper_core::boolean::Boolean;
use bellpepper_core::{ConstraintSystem, SynthesisError, Variable};
use bellpepper_core::boolean::Boolean;
use ff::PrimeField;

use crate::parafold::cycle_fold::AllocatedPrimaryCommitment;
use crate::parafold::cycle_fold::gadgets::emulated::AllocatedBase;
use crate::parafold::cycle_fold::nifs::circuit::AllocatedSecondaryRelaxedR1CSInstance;
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;

#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct AllocatedScalarMulAccumulator<E: CurveCycleEquipped> {
deferred: Vec<AllocatedScalarMulInstance<E>>,
acc: AllocatedSecondaryRelaxedR1CSInstance<E>,
}

impl<E: CurveCycleEquipped> Drop for AllocatedScalarMulAccumulator<E> {
fn drop(&mut self) {
assert!(self.deferred.is_empty(), "unproved scalar multiplications")
}
}

impl<E: CurveCycleEquipped> AllocatedScalarMulAccumulator<E> {
pub fn new(acc: AllocatedSecondaryRelaxedR1CSInstance<E>) -> Self {
Self {
deferred: vec![],
acc,
}
pub fn new() -> Self {
Self { deferred: vec![] }
}

/// Compute the result `C <- A + x * B` by folding a proof over the secondary curve.
Expand Down Expand Up @@ -55,8 +57,9 @@ impl<E: CurveCycleEquipped> AllocatedScalarMulAccumulator<E> {
pub fn finalize<CS>(
mut self,
mut cs: CS,
acc_cf: &mut AllocatedSecondaryRelaxedR1CSInstance<E>,
transcript: &mut AllocatedTranscript<E>,
) -> Result<AllocatedSecondaryRelaxedR1CSInstance<E>, SynthesisError>
) -> Result<(), SynthesisError>
where
CS: ConstraintSystem<E::Scalar>,
{
Expand All @@ -65,14 +68,13 @@ impl<E: CurveCycleEquipped> AllocatedScalarMulAccumulator<E> {

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

Ok(self.acc)
Ok(())
}
}

Expand Down
13 changes: 6 additions & 7 deletions src/parafold/cycle_fold/gadgets/ecc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,25 @@ pub struct AllocatedPoint<G: Group> {
}

impl<G: Group> AllocatedPoint<G> {
pub fn select_default<CS>(self, mut cs: CS, is_default: &Boolean) -> Result<Self, SynthesisError>
pub fn select_default<CS>(&self, mut cs: CS, is_default: &Boolean) -> Result<Self, SynthesisError>
where
CS: ConstraintSystem<G::Base>,
{
let zero = alloc_zero(cs.namespace(|| "alloc 0"));
let one = alloc_one(cs.namespace(|| "alloc 1"));
let Self {
x, y, is_infinity, ..
} = self;
let x = conditionally_select(cs.namespace(|| "select x"), &zero, &x, is_default)?;
let y = conditionally_select(cs.namespace(|| "select y"), &zero, &y, is_default)?;

let x = conditionally_select(cs.namespace(|| "select x"), &zero, &self.x, is_default)?;
let y = conditionally_select(cs.namespace(|| "select y"), &zero, &self.y, is_default)?;
let is_infinity = conditionally_select(
cs.namespace(|| "select is_infinity"),
&one,
&is_infinity,
&self.is_infinity,
is_default,
)?;
Ok(Self { x, y, is_infinity })
}

#[allow(unused)]
pub fn enforce_trivial<CS>(&self, mut cs: CS, is_trivial: &Boolean)
where
CS: ConstraintSystem<G::Base>,
Expand Down
21 changes: 2 additions & 19 deletions src/parafold/cycle_fold/gadgets/emulated.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::marker::PhantomData;
use std::ops::BitAnd;

use bellpepper_core::{ConstraintSystem, SynthesisError, Variable};
use bellpepper_core::boolean::{AllocatedBit, Boolean};
use bellpepper_core::num::{AllocatedNum, Num};
use bellpepper_core::{ConstraintSystem, SynthesisError, Variable};
use bellpepper_emulated::field_element::{
EmulatedFieldElement, EmulatedFieldParams, EmulatedLimbs,
};
use bellpepper_emulated::util::bigint_to_scalar;
use ff::{Field, PrimeField, PrimeFieldBits};
use itertools::{Itertools, zip_eq};
use itertools::{zip_eq, Itertools};
use neptune::circuit2::Elt;
use num_bigint::{BigInt, Sign};
use num_traits::{Num as num_Num, One, Zero};
Expand Down Expand Up @@ -74,17 +74,6 @@ impl<E: CurveCycleEquipped> AllocatedBase<E> {
Self(EmulatedFieldElement::zero())
}

pub fn enforce_zero<CS: ConstraintSystem<E::Scalar>>(&self, mut cs: CS, is_zero: &Boolean) {
for (i, limb) in self.as_preimage().into_iter().enumerate() {
cs.enforce(
|| format!("limb {i} is zero"),
|_| is_zero.lc(CS::one(), E::Scalar::ONE),
|_| limb.lc(),
|lc| lc,
)
}
}

pub fn alloc_limbs<CS: ConstraintSystem<E::Scalar>>(mut cs: CS, limbs: Vec<E::Scalar>) -> Self {
let element = EmulatedFieldElement::new_internal_element(EmulatedLimbs::Constant(limbs), 0)
.allocate_field_element_unchecked(&mut cs.namespace(|| "alloc unchecked"))
Expand Down Expand Up @@ -213,12 +202,6 @@ impl<E: CurveCycleEquipped> AllocatedBase<E> {
0,
))
}

pub fn eq_native(&self, other: &E::Base) -> bool {
let lhs = self.to_big_int();
let rhs = field_to_big_int(other);
lhs == rhs
}
}

pub fn field_to_big_int<F: PrimeField>(f: &F) -> BigInt {
Expand Down
15 changes: 8 additions & 7 deletions src/parafold/cycle_fold/gadgets/secondary_commitment.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use bellpepper_core::{ConstraintSystem, SynthesisError};
use bellpepper_core::boolean::Boolean;
use bellpepper_core::{ConstraintSystem, SynthesisError};
use bitvec::macros::internal::funty::Fundamental;
use neptune::circuit2::Elt;

use crate::Commitment;
use crate::parafold::cycle_fold::gadgets::ecc::AllocatedPoint;
use crate::traits::{CurveCycleEquipped, Engine};
use crate::traits::commitment::CommitmentTrait;
use crate::traits::{CurveCycleEquipped, Engine};
use crate::Commitment;

#[derive(Debug, Clone)]
pub struct AllocatedSecondaryCommitment<E: CurveCycleEquipped> {
Expand All @@ -16,7 +16,7 @@ pub struct AllocatedSecondaryCommitment<E: CurveCycleEquipped> {
impl<E: CurveCycleEquipped> AllocatedSecondaryCommitment<E> {
/// 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, commitment: Commitment<E::Secondary>) -> Self
pub fn alloc_unchecked<CS>(mut cs: CS, commitment: &Commitment<E::Secondary>) -> Self
where
CS: ConstraintSystem<E::Scalar>,
{
Expand Down Expand Up @@ -60,16 +60,17 @@ impl<E: CurveCycleEquipped> AllocatedSecondaryCommitment<E> {
Ok(Self { commitment: res })
}

pub fn select_default<CS>(self, mut cs: CS, is_default: &Boolean) -> Result<Self, SynthesisError>
pub fn select_default<CS>(&self, mut cs: CS, is_default: &Boolean) -> Result<Self, SynthesisError>
where
CS: ConstraintSystem<E::Scalar>,
{
let res = self
let commitment = self
.commitment
.select_default(cs.namespace(|| "select default"), is_default)?;
Ok(Self { commitment: res })
Ok(Self { commitment })
}

#[allow(unused)]
pub fn enforce_trivial<CS>(&self, mut cs: CS, is_trivial: &Boolean)
where
CS: ConstraintSystem<E::Scalar>,
Expand Down
Loading

0 comments on commit 3e45ac5

Please sign in to comment.