Skip to content

Commit

Permalink
Small refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
adr1anh committed Feb 20, 2024
1 parent 58e3041 commit 3fb9da7
Show file tree
Hide file tree
Showing 14 changed files with 124 additions and 142 deletions.
31 changes: 8 additions & 23 deletions src/parafold/cycle_fold/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,20 @@ 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::parafold::transcript::TranscriptConstants;

use crate::traits::Engine;
use crate::Commitment;

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

impl<E1> AllocatedScalarMulAccumulator<E1>
where
E1: Engine,
{
pub fn new(constants: TranscriptConstants<E1>) -> Self {
Self {
constants,
deferred: vec![],
}
}

pub fn alloc_transcript<CS>(
&self,
mut cs: CS,
commitment: Commitment<E1>,
transcript: &mut AllocatedTranscript<E1>,
) -> AllocatedHashedCommitment<E1>
where
CS: ConstraintSystem<E1::Scalar>,
{
let c = AllocatedHashedCommitment::alloc(&mut cs, commitment, &self.constants);
transcript.absorb(c.as_preimage());
c
pub fn new() -> Self {
Self { deferred: vec![] }
}

/// Compute the result `C <- A + x * B` by folding a proof over the secondary curve.
Expand All @@ -57,7 +38,11 @@ where
let B_value = B.value;
let x_value = x.get_value().ok_or(SynthesisError::AssignmentMissing)?;
let C_value = A_value + B_value * x_value;
let C = self.alloc_transcript(cs.namespace(|| "alloc output"), C_value, transcript);
let C = AllocatedHashedCommitment::alloc_transcript(
cs.namespace(|| "alloc output"),
C_value,
transcript,
);

self.deferred.push(AllocatedScalarMulInstance {
A,
Expand Down
31 changes: 22 additions & 9 deletions src/parafold/cycle_fold/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use bellpepper_core::num::AllocatedNum;
use bellpepper_core::ConstraintSystem;
use ff::{Field, PrimeFieldBits};
use neptune::generic_array::typenum::U2;
use neptune::poseidon::PoseidonConstants;
use neptune::Poseidon;

use crate::constants::{BN_LIMB_WIDTH, BN_N_LIMBS};
use crate::parafold::transcript::TranscriptConstants;
use crate::parafold::transcript::circuit::AllocatedTranscript;
use crate::traits::commitment::CommitmentTrait;
use crate::traits::Engine;
use crate::Commitment;
Expand Down Expand Up @@ -47,16 +49,14 @@ pub struct HashedCommitment<E1: Engine> {
point: Commitment<E1>,
// Poseidon hash of (x,y) = point. We set hash = 0 when `point` = infinity
hash: E1::Base,
// E1 representation of `BN_N_LIMBS` limbs with BN_LIMB_WIDTH bits.
// E1 representation of `hash` with `BN_N_LIMBS` limbs of BN_LIMB_WIDTH bits.
hash_limbs: [E1::Scalar; BN_N_LIMBS],
}

impl<E1: Engine> HashedCommitment<E1> {
/// Convert a [Commitment] to it's compressed representation.
///
/// # TODO:
/// - The Poseidon constants for `H(x,y)` over F_q are defined by `constants.1`.
pub fn new(point: Commitment<E1>, constants: &TranscriptConstants<E1>) -> Self {
pub fn new(point: Commitment<E1>) -> Self {
let constants = PoseidonConstants::<E1::Base, U2>::new();
let (x, y, infinity) = point.to_coordinates();
if infinity {
Self {
Expand All @@ -65,7 +65,7 @@ impl<E1: Engine> HashedCommitment<E1> {
hash_limbs: [E1::Scalar::ZERO; BN_N_LIMBS],
}
} else {
let hash = Poseidon::new_with_preimage(&[x, y], &constants.1).hash();
let hash = Poseidon::new_with_preimage(&[x, y], &constants).hash();
let hash_limbs = hash
.to_le_bits()
.chunks_exact(BN_LIMB_WIDTH)
Expand Down Expand Up @@ -113,11 +113,11 @@ pub struct AllocatedHashedCommitment<E1: Engine> {
}

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

pub fn alloc_transcript<CS>(
mut cs: CS,
c: Commitment<E1>,
transcript: &mut AllocatedTranscript<E1>,
) -> Self
where
CS: ConstraintSystem<E1::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>> {
self.hash_limbs.clone()
}
Expand Down
37 changes: 8 additions & 29 deletions src/parafold/cycle_fold/prover.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
use bellpepper_core::ConstraintSystem;

use crate::bellpepper::solver::SatisfyingAssignment;
use crate::parafold::cycle_fold::HashedCommitment;
use crate::parafold::nifs::prover::RelaxedR1CS;
use crate::parafold::nifs::FoldProof;
use crate::parafold::transcript::prover::Transcript;
use crate::parafold::transcript::TranscriptConstants;
use crate::r1cs::R1CSShape;
use crate::traits::Engine;
use crate::{Commitment, CommitmentKey};
Expand All @@ -21,16 +19,12 @@ 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> {
constants: TranscriptConstants<E1>,
deferred: Vec<ScalarMulInstance<E1>>,
}

impl<E1: Engine> ScalarMulAccumulator<E1> {
pub fn new(constants: TranscriptConstants<E1>) -> Self {
Self {
constants,
deferred: vec![],
}
pub fn new() -> Self {
Self { deferred: vec![] }
}

/// Given two commitments `A`, `B` and a scalar `x`, compute `C <- A + x * B`
Expand All @@ -45,27 +39,12 @@ impl<E1: Engine> ScalarMulAccumulator<E1> {
x: E1::Scalar,
transcript: &mut Transcript<E1>,
) -> Commitment<E1> {
let C_value = A + B * x;
let C: Commitment<E1> = A + B * x;

let C = self.add_to_transcript(C_value, transcript);
transcript.absorb_commitment_primary(C.clone());

self.deferred.push(ScalarMulInstance {
A: HashedCommitment::new(A, &self.constants),
B: HashedCommitment::new(B, &self.constants),
x,
C,
});
C_value
}
self.deferred.push(ScalarMulInstance { A, B, x, C });

/// Convert a [Commitment] to a [HashedCommitment] and add it to the transcript.
pub fn add_to_transcript(
&self,
C: Commitment<E1>,
transcript: &mut Transcript<E1>,
) -> HashedCommitment<E1> {
let C = HashedCommitment::new(C, &self.constants);
transcript.absorb(C.hash_limbs);
C
}

Expand Down Expand Up @@ -107,8 +86,8 @@ impl<E1: Engine> ScalarMulAccumulator<E1> {

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct ScalarMulInstance<E1: Engine> {
A: HashedCommitment<E1>,
B: HashedCommitment<E1>,
A: Commitment<E1>,
B: Commitment<E1>,
x: E1::Scalar,
C: HashedCommitment<E1>,
C: Commitment<E1>,
}
30 changes: 19 additions & 11 deletions src/parafold/nifs/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::parafold::transcript::circuit::AllocatedTranscript;
use crate::parafold::transcript::TranscriptConstants;
use crate::traits::Engine;

/// Allocated [RelaxedR1CSInstance]
/// Allocated [RelaxedR1CSInstance] for a circuit over the primary curve.
#[derive(Debug, Clone)]
pub struct AllocatedRelaxedR1CSInstance<E1: Engine> {
u: AllocatedNum<E1::Scalar>,
Expand All @@ -33,8 +33,13 @@ impl<E1: Engine> AllocatedRelaxedR1CSInstance<E1> {
CS: ConstraintSystem<E1::Scalar>,
{
let FoldProof { W: W_new, T } = fold_proof;
let W_new = acc_sm.alloc_transcript(cs.namespace(|| "alloc W_new"), W_new, transcript);
let T = acc_sm.alloc_transcript(cs.namespace(|| "alloc E"), T, transcript);

let W_new = AllocatedHashedCommitment::alloc_transcript(
cs.namespace(|| "alloc W_new"),
W_new,
transcript,
);
let T = AllocatedHashedCommitment::alloc_transcript(cs.namespace(|| "alloc E"), T, transcript);

let r = transcript.squeeze(&mut cs.namespace(|| "squeeze r"))?;

Expand All @@ -53,6 +58,7 @@ impl<E1: Engine> AllocatedRelaxedR1CSInstance<E1> {
mul_add(cs.namespace(|| format!("X_next[{i}]")), &x_curr, x_new, &r)
})
.collect::<Result<Vec<_>, _>>()?;
// W_next = W_curr + r * W_new
let W_next = acc_sm.scalar_mul(
cs.namespace(|| "W_next"),
W_curr.clone(),
Expand Down Expand Up @@ -91,7 +97,13 @@ impl<E1: Engine> AllocatedRelaxedR1CSInstance<E1> {
// Add all cross-term commitments to the transcript.
let Ts = proofs
.into_iter()
.map(|proof| acc_sm.alloc_transcript(cs.namespace(|| "alloc Ts"), proof.T, transcript))
.map(|proof| {
AllocatedHashedCommitment::alloc_transcript(
cs.namespace(|| "alloc Ts"),
proof.T,
transcript,
)
})
.collect::<Vec<_>>();

// Get common challenge
Expand Down Expand Up @@ -169,11 +181,7 @@ impl<E1: Engine> AllocatedRelaxedR1CSInstance<E1> {
transcript.squeeze(&mut cs)
}

pub fn alloc<CS>(
mut cs: CS,
instance: RelaxedR1CSInstance<E1>,
constants: &TranscriptConstants<E1>,
) -> Self
pub fn alloc<CS>(mut cs: CS, instance: RelaxedR1CSInstance<E1>) -> Self
where
CS: ConstraintSystem<E1::Scalar>,
{
Expand All @@ -185,8 +193,8 @@ impl<E1: Engine> AllocatedRelaxedR1CSInstance<E1> {
.enumerate()
.map(|(i, X)| AllocatedNum::alloc_infallible(cs.namespace(|| format!("alloc X[{i}]")), || X))
.collect();
let W = AllocatedHashedCommitment::alloc(cs.namespace(|| "alloc W"), W, constants);
let E = AllocatedHashedCommitment::alloc(cs.namespace(|| "alloc E"), E, constants);
let W = AllocatedHashedCommitment::alloc(cs.namespace(|| "alloc W"), W);
let E = AllocatedHashedCommitment::alloc(cs.namespace(|| "alloc E"), E);

Self { u, X, W, E }
}
Expand Down
10 changes: 9 additions & 1 deletion src/parafold/nifs/circuit_secondary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ where

let FoldProof { W: W_new, T } = fold_proof;

// Allocate W_new, T and add them to the transcript
let W_new = AllocatedPoint::alloc_transcript::<_, E1, E2>(
cs.namespace(|| "alloc W_new"),
W_new,
Expand All @@ -57,6 +58,7 @@ where
let T =
AllocatedPoint::alloc_transcript::<_, E1, E2>(cs.namespace(|| "alloc T"), T, transcript);

// Get challenge `r` but truncate the bits for more efficient scalar multiplication
let r_bits = transcript.squeeze_bits(cs.namespace(|| "r bits"), NUM_CHALLENGE_BITS)?;
let r = le_bits_to_num(cs.namespace(|| "r"), &r_bits)?;
let r_bn = BigNat::from_num(
Expand All @@ -65,13 +67,15 @@ where
BN_LIMB_WIDTH,
BN_N_LIMBS,
)?;

let Self {
u: u_curr,
X: X_curr,
W: W_curr,
E: E_curr,
} = self;

// We have to do a full modular reduction since merging will make `u` full-sized
let u_next = u_curr
.add(&r_bn)?
.red_mod(cs.namespace(|| "u_next = u_curr + r % q"), &q_bn)?;
Expand All @@ -88,6 +92,7 @@ where
})
.collect::<Result<Vec<_>, _>>()?;

// Scalar multiplications
let W_next = W_new
.scalar_mul(cs.namespace(|| "r * W_new"), &r_bits)?
.add(cs.namespace(|| "W_curr + r * W_new"), W_curr)?;
Expand Down Expand Up @@ -124,10 +129,12 @@ where

let MergeProof { T } = merge_proof;

// Allocate T and add to transcript
let T =
AllocatedPoint::alloc_transcript::<_, E1, E2>(cs.namespace(|| "alloc T"), T, transcript);
transcript.absorb(T.as_preimage());

// Get truncated challenge
let r_bits = transcript.squeeze_bits(cs.namespace(|| "r bits"), NUM_CHALLENGE_BITS)?;
let r = le_bits_to_num(cs.namespace(|| "r"), &r_bits)?;
let r_bn = BigNat::from_num(
Expand Down Expand Up @@ -199,7 +206,7 @@ where
.enforce_trivial(cs.namespace(|| "enforce trivial E"), is_trivial);
}

pub fn alloc<CS>(/*mut*/ _cs: CS, _instance: RelaxedR1CSInstance<E2>) -> Self
fn alloc<CS>(/*mut*/ _cs: CS, _instance: RelaxedR1CSInstance<E2>) -> Self
where
CS: ConstraintSystem<E1::Scalar>,
{
Expand All @@ -223,6 +230,7 @@ where
// }
}

/// Allocate and add the result to the transcript
pub fn alloc_transcript<CS>(
mut cs: CS,
instance: RelaxedR1CSInstance<E2>,
Expand Down
22 changes: 11 additions & 11 deletions src/parafold/nifs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ pub mod prover;

/// Instance of a Relaxed-R1CS accumulator for a circuit.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RelaxedR1CSInstance<E1: Engine> {
pub struct RelaxedR1CSInstance<E: Engine> {
// TODO: Add pp_digest for this circuit.
u: E1::Scalar,
X: Vec<E1::Scalar>,
W: Commitment<E1>,
E: Commitment<E1>,
u: E::Scalar,
X: Vec<E::Scalar>,
W: Commitment<E>,
E: Commitment<E>,
}

/// A proof for folding a statement X of a circuit C into a Relaxed-R1CS circuit for the same circuit C
/// A proof for folding a statement X of a circuit C into a Relaxed-R1CS accumulator for the same circuit C
#[derive(Debug, Clone, Default)]
pub struct FoldProof<E1: Engine> {
W: Commitment<E1>,
T: Commitment<E1>,
pub struct FoldProof<E: Engine> {
W: Commitment<E>,
T: Commitment<E>,
}

/// A proof for merging two valid Relaxed-R1CS accumulators for the same circuit C
#[derive(Debug, Clone)]
pub struct MergeProof<E1: Engine> {
T: Commitment<E1>,
pub struct MergeProof<E: Engine> {
T: Commitment<E>,
}
Loading

0 comments on commit 3fb9da7

Please sign in to comment.