Skip to content

Commit

Permalink
Adapt to CurveCycleEquiped
Browse files Browse the repository at this point in the history
  • Loading branch information
adr1anh committed Feb 20, 2024
1 parent 18f9fe6 commit 64db5b5
Show file tree
Hide file tree
Showing 15 changed files with 517 additions and 580 deletions.
35 changes: 17 additions & 18 deletions src/parafold/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@ use crate::parafold::nivc::{NIVCMergeProof, NIVCUpdateProof, NIVCIO};
use crate::parafold::transcript::circuit::AllocatedTranscript;
use crate::parafold::transcript::TranscriptConstants;
use crate::supernova::StepCircuit;
use crate::traits::Engine;
use crate::traits::CurveCycleEquipped;

pub fn synthesize_step<E1, E2, CS, SF>(
pub fn synthesize_step<E, CS, SF>(
mut cs: CS,
ro_consts: &TranscriptConstants<E1>,
proof: NIVCUpdateProof<E1, E2>,
ro_consts: &TranscriptConstants<E::Scalar>,
proof: NIVCUpdateProof<E>,
step_circuit: &SF,
) -> Result<NIVCIO<E1::Scalar>, SynthesisError>
) -> Result<NIVCIO<E::Scalar>, SynthesisError>
where
E1: Engine,
E2: Engine<Scalar = E1::Base, Base = E1::Scalar>,
CS: ConstraintSystem<E1::Scalar>,
SF: StepCircuit<E1::Scalar>,
E: CurveCycleEquipped,
CS: ConstraintSystem<E::Scalar>,
SF: StepCircuit<E::Scalar>,
{
// Fold proof for previous state
let (mut state, transcript) =
Expand All @@ -30,18 +29,18 @@ where

io
}

/// Circuit
pub fn synthesize_merge<E1, E2, CS>(
pub fn synthesize_merge<E, CS>(
mut cs: CS,
ro_consts: &TranscriptConstants<E1>,
proof_L: NIVCUpdateProof<E1, E2>,
proof_R: NIVCUpdateProof<E1, E2>,
proof_merge: NIVCMergeProof<E1, E2>,
) -> Result<NIVCIO<E1::Scalar>, SynthesisError>
ro_consts: &TranscriptConstants<E::Scalar>,
proof_L: NIVCUpdateProof<E>,
proof_R: NIVCUpdateProof<E>,
proof_merge: NIVCMergeProof<E>,
) -> Result<NIVCIO<E::Scalar>, SynthesisError>
where
E1: Engine,
E2: Engine<Scalar = E1::Base, Base = E1::Scalar>,
CS: ConstraintSystem<E1::Scalar>,
E: CurveCycleEquipped,
CS: ConstraintSystem<E::Scalar>,
{
// Verify L
let (self_L, transcript_L) =
Expand Down
53 changes: 25 additions & 28 deletions src/parafold/cycle_fold/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,14 @@ use crate::parafold::cycle_fold::AllocatedHashedCommitment;
use crate::parafold::nifs::circuit_secondary::AllocatedSecondaryRelaxedR1CSInstance;
use crate::parafold::nifs::FoldProof;
use crate::parafold::transcript::circuit::AllocatedTranscript;

use crate::traits::Engine;
use crate::traits::{CurveCycleEquipped, Engine};

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

impl<E1> AllocatedScalarMulAccumulator<E1>
where
E1: Engine,
{
impl<E: Engine> AllocatedScalarMulAccumulator<E> {
pub fn new() -> Self {
Self { deferred: vec![] }
}
Expand All @@ -26,13 +22,13 @@ where
pub fn scalar_mul<CS>(
&mut self,
mut cs: CS,
A: AllocatedHashedCommitment<E1>,
B: AllocatedHashedCommitment<E1>,
x: AllocatedNum<E1::Scalar>,
transcript: &mut AllocatedTranscript<E1>,
) -> Result<AllocatedHashedCommitment<E1>, SynthesisError>
A: AllocatedHashedCommitment<E>,
B: AllocatedHashedCommitment<E>,
x: AllocatedNum<E::Scalar>,
transcript: &mut AllocatedTranscript<E::Scalar>,
) -> Result<AllocatedHashedCommitment<E>, SynthesisError>
where
CS: ConstraintSystem<E1::Scalar>,
CS: ConstraintSystem<E::Scalar>,
{
let A_value = A.value;
let B_value = B.value;
Expand All @@ -59,17 +55,18 @@ where
self_L.deferred.append(&mut self_R.deferred);
self_L
}
}

pub fn finalize<CS, E2>(
impl<E: CurveCycleEquipped> AllocatedScalarMulAccumulator<E> {
pub fn finalize<CS>(
self,
mut cs: CS,
mut acc_cf: AllocatedSecondaryRelaxedR1CSInstance<E1, E2>,
proofs: impl IntoIterator<Item = FoldProof<E2>>,
transcript: &mut AllocatedTranscript<E1>,
) -> Result<AllocatedSecondaryRelaxedR1CSInstance<E1, E2>, SynthesisError>
mut acc_cf: AllocatedSecondaryRelaxedR1CSInstance<E>,
proofs: impl IntoIterator<Item = FoldProof<E::Secondary>>,
transcript: &mut AllocatedTranscript<E::Scalar>,
) -> Result<AllocatedSecondaryRelaxedR1CSInstance<E>, SynthesisError>
where
CS: ConstraintSystem<E1::Scalar>,
E2: Engine<Base = E1::Scalar>,
CS: ConstraintSystem<E::Scalar>,
{
for (instance, proof) in zip_eq(self.deferred, proofs) {
let AllocatedScalarMulInstance { A, B, x, C } = instance;
Expand All @@ -91,15 +88,15 @@ where
}

#[derive(Debug, Clone)]
pub struct AllocatedScalarMulInstance<E1: Engine> {
A: AllocatedHashedCommitment<E1>,
B: AllocatedHashedCommitment<E1>,
x: AllocatedNum<E1::Scalar>,
C: AllocatedHashedCommitment<E1>,
pub struct AllocatedScalarMulInstance<E: Engine> {
A: AllocatedHashedCommitment<E>,
B: AllocatedHashedCommitment<E>,
x: AllocatedNum<E::Scalar>,
C: AllocatedHashedCommitment<E>,
}

impl<E1: Engine> AllocatedScalarMulInstance<E1> {
pub fn as_preimage(&self) -> impl IntoIterator<Item = AllocatedNum<E1::Scalar>> + '_ {
impl<E: Engine> AllocatedScalarMulInstance<E> {
pub fn as_preimage(&self) -> impl IntoIterator<Item = AllocatedNum<E::Scalar>> + '_ {
chain![
self.A.as_preimage(),
self.B.as_preimage(),
Expand Down
48 changes: 24 additions & 24 deletions src/parafold/cycle_fold/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,24 @@ pub mod prover;
/// so this additional hashing that occurs in the secondary circuit ensure we only need to perform this expensive
/// operation 4 times. Moreover, the fact that r<q ensures that the scalar x \in F_r can be trivially embedded into F_q.
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct HashedCommitment<E1: Engine> {
point: Commitment<E1>,
pub struct HashedCommitment<E: Engine> {
point: Commitment<E>,
// Poseidon hash of (x,y) = point. We set hash = 0 when `point` = infinity
hash: E1::Base,
hash: E::Base,
// E1 representation of `hash` with `BN_N_LIMBS` limbs of BN_LIMB_WIDTH bits.
hash_limbs: [E1::Scalar; BN_N_LIMBS],
hash_limbs: [E::Scalar; BN_N_LIMBS],
}

impl<E1: Engine> HashedCommitment<E1> {
impl<E: Engine> HashedCommitment<E> {
/// Convert a [Commitment] to it's compressed representation.
pub fn new(point: Commitment<E1>) -> Self {
let constants = PoseidonConstants::<E1::Base, U2>::new();
pub fn new(point: Commitment<E>) -> Self {
let constants = PoseidonConstants::<E::Base, U2>::new();
let (x, y, infinity) = point.to_coordinates();
if infinity {
Self {
point,
hash: E1::Base::ZERO,
hash_limbs: [E1::Scalar::ZERO; BN_N_LIMBS],
hash: E::Base::ZERO,
hash_limbs: [E::Scalar::ZERO; BN_N_LIMBS],
}
} else {
let hash = Poseidon::new_with_preimage(&[x, y], &constants).hash();
Expand All @@ -71,17 +71,17 @@ impl<E1: Engine> HashedCommitment<E1> {
.chunks_exact(BN_LIMB_WIDTH)
.map(|limb_bits| {
// TODO: Find more efficient trick
let mut limb = E1::Scalar::ZERO;
let mut limb = E::Scalar::ZERO;
for bit in limb_bits.iter().rev() {
// double limb
limb += limb;
if *bit {
limb += E1::Scalar::ONE;
limb += E::Scalar::ONE;
}
}
limb
})
.collect::<Vec<E1::Scalar>>();
.collect::<Vec<E::Scalar>>();

Self {
point,
Expand All @@ -91,7 +91,7 @@ impl<E1: Engine> HashedCommitment<E1> {
}
}

pub fn as_preimage(&self) -> impl IntoIterator<Item = E1::Scalar> {
pub fn as_preimage(&self) -> impl IntoIterator<Item = E::Scalar> {
self.hash_limbs
}
}
Expand All @@ -106,18 +106,18 @@ impl<E1: Engine> HashedCommitment<E1> {
/// - Investigate whether a `is_infinity` flag is needed. It could be used to avoid synthesizing secondary circuits
/// when the scalar multiplication is trivial.
#[derive(Debug, Clone)]
pub struct AllocatedHashedCommitment<E1: Engine> {
value: Commitment<E1>,
pub struct AllocatedHashedCommitment<E: Engine> {
value: Commitment<E>,
// hash = if let Some(point) = value { H_secondary(point) } else { 0 }
hash_limbs: [AllocatedNum<E1::Scalar>; BN_N_LIMBS],
hash_limbs: [AllocatedNum<E::Scalar>; BN_N_LIMBS],
}

impl<E1: Engine> AllocatedHashedCommitment<E1> {
pub fn alloc<CS>(mut cs: CS, c: Commitment<E1>) -> Self
impl<E: Engine> AllocatedHashedCommitment<E> {
pub fn alloc<CS>(mut cs: CS, c: Commitment<E>) -> Self
where
CS: ConstraintSystem<E1::Scalar>,
CS: ConstraintSystem<E::Scalar>,
{
let hashed = HashedCommitment::<E1>::new(c);
let hashed = HashedCommitment::<E>::new(c);
let hash_limbs = hashed
.hash_limbs
.map(|limb| AllocatedNum::alloc_infallible(cs.namespace(|| "alloc limb"), || limb));
Expand All @@ -130,18 +130,18 @@ impl<E1: Engine> AllocatedHashedCommitment<E1> {

pub fn alloc_transcript<CS>(
mut cs: CS,
c: Commitment<E1>,
transcript: &mut AllocatedTranscript<E1>,
c: Commitment<E>,
transcript: &mut AllocatedTranscript<E::Scalar>,
) -> Self
where
CS: ConstraintSystem<E1::Scalar>,
CS: ConstraintSystem<E::Scalar>,
{
let c = AllocatedHashedCommitment::alloc(&mut cs, c);
transcript.absorb(c.as_preimage());
c
}

pub fn as_preimage(&self) -> impl IntoIterator<Item = AllocatedNum<E1::Scalar>> {
pub fn as_preimage(&self) -> impl IntoIterator<Item = AllocatedNum<E::Scalar>> {
self.hash_limbs.clone()
}
}
63 changes: 31 additions & 32 deletions src/parafold/cycle_fold/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::parafold::nifs::prover::RelaxedR1CS;
use crate::parafold::nifs::FoldProof;
use crate::parafold::transcript::prover::Transcript;
use crate::r1cs::R1CSShape;
use crate::traits::Engine;
use crate::traits::{CurveCycleEquipped, Dual, Engine};
use crate::{Commitment, CommitmentKey};

/// A [ScalarMulAccumulator] represents a coprocessor for efficiently computing non-native ECC scalar multiplications
Expand All @@ -18,11 +18,11 @@ use crate::{Commitment, CommitmentKey};
///
/// All operations are proved in a batch at the end of the circuit in order to minimize latency for the prover.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScalarMulAccumulator<E1: Engine> {
deferred: Vec<ScalarMulInstance<E1>>,
pub struct ScalarMulAccumulator<E: Engine> {
deferred: Vec<ScalarMulInstance<E>>,
}

impl<E1: Engine> ScalarMulAccumulator<E1> {
impl<E: Engine> ScalarMulAccumulator<E> {
pub fn new() -> Self {
Self { deferred: vec![] }
}
Expand All @@ -34,60 +34,59 @@ impl<E1: Engine> ScalarMulAccumulator<E1> {
/// The tuple `[A, B, x, C]` is added to the `deferred` list which will be proved in a batch later on.
pub fn scalar_mul(
&mut self,
A: Commitment<E1>,
B: Commitment<E1>,
x: E1::Scalar,
transcript: &mut Transcript<E1>,
) -> Commitment<E1> {
let C: Commitment<E1> = A + B * x;
A: Commitment<E>,
B: Commitment<E>,
x: E::Scalar,
transcript: &mut Transcript<E::Scalar>,
) -> Commitment<E> {
let C: Commitment<E> = A + B * x;

transcript.absorb_commitment_primary(C.clone());
transcript.absorb_commitment_primary::<E>(C.clone());

self.deferred.push(ScalarMulInstance { A, B, x, C });

C
}
}

impl<E: CurveCycleEquipped> ScalarMulAccumulator<E> {
/// Consume all deferred scalar multiplication instances and create a folding proof for each result.
/// The proofs are folded into a mutable RelaxedR1CS for the corresponding circuit over the secondary curve.
pub fn finalize<E2>(
pub fn finalize(
self,
ck: &CommitmentKey<E2>,
shape: &R1CSShape<E2>,
acc_cf: &mut RelaxedR1CS<E2>,
transcript: &mut Transcript<E1>,
) -> Vec<FoldProof<E2>>
where
E2: Engine<Scalar = E1::Base, Base = E1::Scalar>,
{
ck: &CommitmentKey<E::Secondary>,
shape: &R1CSShape<E::Secondary>,
acc_cf: &mut RelaxedR1CS<E::Secondary>,
transcript: &mut Transcript<E::Scalar>,
) -> Vec<FoldProof<E::Secondary>> {
self
.deferred
.into_iter()
.map(|_instance| {
let cs = SatisfyingAssignment::<E2>::new();
let cs = SatisfyingAssignment::<Dual<E>>::new();
// TODO: synthesize the circuit that proves `instance`
let (X, W) = cs.to_assignments();
acc_cf.fold_secondary(ck, shape, X, &W, transcript)
acc_cf.fold_secondary::<E>(ck, shape, X, &W, transcript)
})
.collect()
}

pub fn simulate_finalize<E2>(self, transcript: &mut Transcript<E1>) -> Vec<FoldProof<E2>>
where
E2: Engine<Scalar = E1::Base, Base = E1::Scalar>,
{
pub fn simulate_finalize(
self,
transcript: &mut Transcript<E::Scalar>,
) -> Vec<FoldProof<E::Secondary>> {
self
.deferred
.into_iter()
.map(|_| RelaxedR1CS::<E2>::simulate_fold_secondary(transcript))
.map(|_| RelaxedR1CS::simulate_fold_secondary::<E>(transcript))
.collect()
}
}

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ScalarMulInstance<E1: Engine> {
A: Commitment<E1>,
B: Commitment<E1>,
x: E1::Scalar,
C: Commitment<E1>,
pub struct ScalarMulInstance<E: Engine> {
A: Commitment<E>,
B: Commitment<E>,
x: E::Scalar,
C: Commitment<E>,
}
Loading

0 comments on commit 64db5b5

Please sign in to comment.