Skip to content

Commit

Permalink
revamp
Browse files Browse the repository at this point in the history
  • Loading branch information
adr1anh committed Jan 30, 2024
1 parent 40968c8 commit 051039a
Show file tree
Hide file tree
Showing 26 changed files with 2,012 additions and 1,636 deletions.
69 changes: 69 additions & 0 deletions src/parafold/circuit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use bellpepper_core::{ConstraintSystem, SynthesisError};

use crate::parafold::nivc::circuit::AllocatedNIVCState;
use crate::parafold::nivc::{NIVCMergeProof, NIVCUpdateProof, NIVCIO};
use crate::parafold::transcript::circuit::AllocatedTranscript;
use crate::parafold::transcript::TranscriptConstants;
use crate::traits::circuit_supernova::EnforcingStepCircuit;
use crate::traits::Engine;

pub fn synthesize_step<E1, E2, CS, SF>(
mut cs: CS,
ro_consts: &TranscriptConstants<E1>,
proof: NIVCUpdateProof<E1, E2>,
step_circuit: &SF,
) -> Result<NIVCIO<E1::Scalar>, SynthesisError>
where
E1: Engine,
E2: Engine<Scalar = E1::Base, Base = E1::Scalar>,
CS: ConstraintSystem<E1::Scalar>,
SF: EnforcingStepCircuit<E1::Scalar>,
{
// Fold proof for previous state
let (mut state, transcript) =
AllocatedNIVCState::from_proof(cs.namespace(|| "verify self"), ro_consts, proof)?;

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

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

io
}
/// Circuit
pub fn synthesize_merge<E1, E2, 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>
where
E1: Engine,
E2: Engine<Scalar = E1::Base, Base = E1::Scalar>,
CS: ConstraintSystem<E1::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)
}
129 changes: 95 additions & 34 deletions src/parafold/cycle_fold/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,125 @@
use bellpepper_core::num::AllocatedNum;
use bellpepper_core::{ConstraintSystem, SynthesisError};
use itertools::{chain, zip_eq};

use crate::parafold::cycle_fold::{
AllocatedHashedCommitment, AllocatedScalarMulAccumulator, AllocatedScalarMulFoldProof,
AllocatedScalarMulMergeProof,
};
use crate::parafold::nifs_secondary::AllocatedSecondaryRelaxedR1CSInstance;
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;

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

impl<E1> AllocatedScalarMulAccumulator<E1>
where
E1: Engine,
E2: Engine<Base = E1::Scalar>,
{
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
}

/// Compute the result `C <- A + x * B` by folding a proof over the secondary curve.
pub fn scalar_mul<CS>(
&mut self,
/*mut*/ cs: CS,
mut cs: CS,
A: AllocatedHashedCommitment<E1>,
B: AllocatedHashedCommitment<E1>,
_x: AllocatedNum<E1::Scalar>,
proof: AllocatedScalarMulFoldProof<E1, E2>,
x: AllocatedNum<E1::Scalar>,
transcript: &mut AllocatedTranscript<E1>,
) -> Result<AllocatedHashedCommitment<E1>, SynthesisError>
where
CS: ConstraintSystem<E1::Scalar>,
{
let AllocatedScalarMulFoldProof { output, proof } = proof;
transcript.absorb(&output);

let X_new = vec![
A.hash,
B.hash,
// TODO: alloc x as big nat
// BigNat::(cs.namespace(|| "alloc x"), Some(x))?,
output.hash.clone(),
];
let A_value = A.value;
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);

self.acc.fold(cs, X_new, proof, transcript)?;
self.deferred.push(AllocatedScalarMulInstance {
A,
B,
x,
C: C.clone(),
});

Ok(output)
Ok(C)
}

/// Merges another existing [AllocatedScalarMulAccumulator] into `self`
pub fn merge<CS>(
cs: CS,
self_L: Self,
self_R: Self,
proof: AllocatedScalarMulMergeProof<E1, E2>,
pub fn merge(mut self_L: Self, mut self_R: Self) -> Self {
self_L.deferred.append(&mut self_R.deferred);
self_L
}

pub fn finalize<CS, E2>(
self,
mut cs: CS,
mut acc_cf: AllocatedSecondaryRelaxedR1CSInstance<E1, E2>,
proofs: impl IntoIterator<Item = FoldProof<E2>>,
transcript: &mut AllocatedTranscript<E1>,
) -> Result<Self, SynthesisError>
) -> Result<AllocatedSecondaryRelaxedR1CSInstance<E1, E2>, SynthesisError>
where
CS: ConstraintSystem<E1::Scalar>,
E2: Engine<Base = E1::Scalar>,
{
let Self { acc: acc_L } = self_L;
let Self { acc: acc_R } = self_R;
let AllocatedScalarMulMergeProof { proof } = proof;
let acc_next =
AllocatedSecondaryRelaxedR1CSInstance::merge(cs, acc_L, acc_R, proof, transcript)?;
Ok(Self { acc: acc_next })
for (instance, proof) in zip_eq(self.deferred, proofs) {
let AllocatedScalarMulInstance { A, B, x, C } = instance;
let _X_tmp: Vec<_> = chain![A.as_preimage(), B.as_preimage(), [x], C.as_preimage()].collect();

// TODO: In order to avoid computing unnecessary proofs, we can check
// - x = 0 => C = A

// Convert the elements in the instance to a bignum modulo E1::Base.
// Since |E1::Scalar| < |E1::Base|, we can create the limbs without an initial bound-check
// We should check here that the limbs are of the right size, but not-necessarily bound check them.
// X = [A.as_bignum(), B.as_bignum(), x.as_bignum(), C.as_bignum()]
let X = vec![];
acc_cf.fold(cs.namespace(|| "fold cf instance"), X, proof, transcript)?;
}

Ok(acc_cf)
}
}

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

impl<E1: Engine> AllocatedScalarMulInstance<E1> {
pub fn as_preimage(&self) -> impl IntoIterator<Item = AllocatedNum<E1::Scalar>> + '_ {
chain![
self.A.as_preimage(),
self.B.as_preimage(),
[self.x.clone()],
self.C.as_preimage()
]
}
}
96 changes: 0 additions & 96 deletions src/parafold/cycle_fold/circuit_alloc.rs

This file was deleted.

Loading

0 comments on commit 051039a

Please sign in to comment.