Skip to content

Commit

Permalink
feat(ivc): sangria in cyclefold
Browse files Browse the repository at this point in the history
**Motivation**
In #369 we have to minimize the paired circuit with sangria

**Overview**
I've reused almost all fold-fn (except `instance`) from the existing sangria implementation
  • Loading branch information
cyphersnake committed Dec 16, 2024
1 parent afe45f9 commit 3260960
Show file tree
Hide file tree
Showing 7 changed files with 454 additions and 172 deletions.
7 changes: 7 additions & 0 deletions src/gadgets/ecc/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ pub struct AssignedPoint<C: CurveAffine> {
pub(crate) y: AssignedValue<C::Base>,
}

impl<C: CurveAffine> From<AssignedPoint<C>> for (AssignedValue<C::Base>, AssignedValue<C::Base>) {
fn from(p: AssignedPoint<C>) -> (AssignedValue<C::Base>, AssignedValue<C::Base>) {
let AssignedPoint { x, y } = p;
(x, y)
}
}

impl<C: CurveAffine> AssignedPoint<C> {
pub fn coordinates(&self) -> (&AssignedValue<C::Base>, &AssignedValue<C::Base>) {
(&self.x, &self.y)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ where
};

let (primary_plonk_structure, initial_primary_trace) = {
let mut mock_sfc = StepFoldingCircuit::<A1, CMain, SC> {
let mut mock_sfc = StepFoldingCircuit::<A1, CMain, CSup, SC> {
sc: primary_sfc,
input: sfc::Input::<A1, CMain::ScalarExt>::new_initial::<CMain, CSup>(
&PlonkStructure {
Expand All @@ -123,6 +123,7 @@ where
&support_plonk_structure,
&initial_support_trace.u,
),
_p: PhantomData,
};

let mock_instances = mock_sfc.initial_instances();
Expand All @@ -142,13 +143,14 @@ where
.try_collect_plonk_structure()
.unwrap();

let sfc = StepFoldingCircuit::<A1, CMain, SC> {
let sfc = StepFoldingCircuit::<A1, CMain, CSup, SC> {
sc: primary_sfc,
input: sfc::Input::<A1, CMain::ScalarExt>::new_initial::<CMain, CSup>(
&mock_S,
&support_plonk_structure,
&initial_support_trace.u,
),
_p: PhantomData,
};

// TODO #369 Use expected out marker, instead of zero
Expand Down
25 changes: 18 additions & 7 deletions src/ivc/cyclefold/sfc/input/assigned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
main_gate::{self, AdviceCyclicAssignor, AssignedValue, MainGate, RegionCtx, WrapValue},
};

pub type MainGateConfig = main_gate::MainGateConfig<{ super::super::T_MAIN_GATE }>;
pub type MainGateConfig = main_gate::MainGateConfig<{ super::super::MAIN_GATE_T }>;

pub type BigUint<F> = Vec<F>;

Expand Down Expand Up @@ -76,7 +76,7 @@ impl<F: PrimeField> ProtoGalaxyAccumulatorInstance<F> {
})
}

fn conditional_select<const T: usize>(
pub fn conditional_select<const T: usize>(
region: &mut RegionCtx<'_, F>,
mg: &MainGate<F, T>,
lhs: &Self,
Expand Down Expand Up @@ -272,10 +272,11 @@ impl<F: PrimeField> PairedPlonkInstance<F> {
}
}

#[derive(Clone)]
pub struct SangriaAccumulatorInstance<F: PrimeField> {
pub(crate) ins: PairedPlonkInstance<F>,
pub(crate) E_commitment: (AssignedValue<F>, AssignedValue<F>),
pub(crate) u: BigUint<AssignedValue<F>>,
pub(crate) u: AssignedValue<F>,
}

impl<F: PrimeField> SangriaAccumulatorInstance<F> {
Expand All @@ -302,10 +303,20 @@ impl<F: PrimeField> SangriaAccumulatorInstance<F> {
original.E_commitment.1,
)?,
),
u: assigner.assign_all_advice(region, || "u", original.u.limbs().iter().cloned())?,
u: assigner.assign_next_advice(region, || "u", original.u)?,
})
}

pub fn conditional_select<const T: usize>(
_region: &mut RegionCtx<'_, F>,
_mg: &MainGate<F, T>,
_lhs: &Self,
_rhs: &Self,
_cond: &AssignedValue<F>,
) -> Result<Self, Halo2PlonkError> {
todo!()
}

fn iter_wrap_values(&self) -> impl '_ + Iterator<Item = WrapValue<F>> {
let Self {
ins,
Expand All @@ -316,7 +327,7 @@ impl<F: PrimeField> SangriaAccumulatorInstance<F> {
ins.iter_wrap_values().chain(
[E_commitment.0.clone(), E_commitment.1.clone()]
.into_iter()
.chain(u.iter().cloned())
.chain(iter::once(u.clone()))
.map(|v| WrapValue::Assigned(v)),
)
}
Expand All @@ -329,7 +340,7 @@ pub struct PairedTrace<F: PrimeField> {
// The size from one to three
// Depdend on `W_commitments_len`
pub incoming: Box<[PairedPlonkInstance<F>]>,
proof: SangriaCrossTermCommits<F>,
pub proof: SangriaCrossTermCommits<F>,
}

impl<F: PrimeField> PairedTrace<F> {
Expand Down Expand Up @@ -377,7 +388,7 @@ impl<F: PrimeField> PairedTrace<F> {
})
}

fn iter_wrap_values(&self) -> impl '_ + Iterator<Item = WrapValue<F>> {
pub fn iter_wrap_values(&self) -> impl '_ + Iterator<Item = WrapValue<F>> {
let Self {
input_accumulator,
incoming,
Expand Down
11 changes: 7 additions & 4 deletions src/ivc/cyclefold/sfc/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl<F: PrimeField> SelfTrace<F> {
pub struct SangriaAccumulatorInstance<F: PrimeField> {
pub(crate) ins: PairedPlonkInstance<F>,
pub(crate) E_commitment: (F, F),
pub(crate) u: BigUint<F>,
pub(crate) u: F,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for SangriaAccumulatorInstance<F> {
Expand All @@ -168,7 +168,10 @@ impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for SangriaAccumulatorInst
u,
} = self;

ro.absorb(ins).absorb_field(*ex).absorb_field(*ey).absorb(u);
ro.absorb(ins)
.absorb_field(*ex)
.absorb_field(*ey)
.absorb_field(*u);
}
}

Expand Down Expand Up @@ -246,7 +249,7 @@ impl<F: PrimeField> PairedTrace<F> {
input_accumulator: SangriaAccumulatorInstance {
ins: ins.clone(),
E_commitment: (F::ZERO, F::ZERO),
u: BigUint::zero(DEFAULT_LIMB_WIDTH),
u: F::ZERO,
},
incoming: vec![ins.clone(); W_commitments_len].into_boxed_slice(),
proof: vec![
Expand Down Expand Up @@ -353,7 +356,7 @@ impl<const ARITY: usize, F: PrimeField> Input<ARITY, F> {
challenges: vec![random_big_uint(&mut gen); 1],
},
E_commitment: (gen.next().unwrap(), gen.next().unwrap()),
u: random_big_uint(&mut gen),
u: gen.next().unwrap(),
},
incoming: vec![
PairedPlonkInstance {
Expand Down
91 changes: 67 additions & 24 deletions src/ivc/cyclefold/sfc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::num::NonZeroUsize;
use std::{marker::PhantomData, num::NonZeroUsize};

use itertools::Itertools;
use tracing::error;
Expand All @@ -21,58 +21,70 @@ use crate::{
mod input;
pub use input::Input;

pub mod sangria_adapter;

use crate::halo2_proofs::halo2curves::ff::{FromUniformBytes, PrimeField, PrimeFieldBits};

const T_MAIN_GATE: usize = 5;
const MAIN_GATE_T: usize = 5;

/// 'SCC' here is 'Step Circuit Config'
#[derive(Debug, Clone)]
pub struct Config<SCC> {
sc: SCC,
mg: MainGateConfig<T_MAIN_GATE>,
mg: MainGateConfig<MAIN_GATE_T>,
}

pub struct StepFoldingCircuit<
'sc,
const ARITY: usize,
C: CurveAffine,
SC: StepCircuit<ARITY, C::ScalarExt>,
CMain: CurveAffine,
CSup: CurveAffine<Base = CMain::ScalarExt>,
SC: StepCircuit<ARITY, CMain::ScalarExt>,
> {
pub sc: &'sc SC,
pub input: Input<ARITY, C::ScalarExt>,
pub input: Input<ARITY, CMain::ScalarExt>,
pub _p: PhantomData<CSup>,
}

impl<const ARITY: usize, C: CurveAffine, SC: StepCircuit<ARITY, C::ScalarExt>>
StepFoldingCircuit<'_, ARITY, C, SC>
impl<
const ARITY: usize,
CMain: CurveAffine,
CSup: CurveAffine<Base = CMain::ScalarExt>,
SC: StepCircuit<ARITY, CMain::ScalarExt>,
> StepFoldingCircuit<'_, ARITY, CMain, CSup, SC>
where
C::ScalarExt: PrimeFieldBits + FromUniformBytes<64>,
CMain::ScalarExt: PrimeFieldBits + FromUniformBytes<64>,
{
/// For the initial iteration, we will give the same accumulators that we take from the input
pub fn initial_instances(&self) -> Vec<Vec<C::ScalarExt>> {
let marker = cyclefold::ro()
.absorb(&self.input)
.output(NonZeroUsize::new(<C::ScalarExt as PrimeField>::NUM_BITS as usize).unwrap());
pub fn initial_instances(&self) -> Vec<Vec<CMain::ScalarExt>> {
let marker = cyclefold::ro().absorb(&self.input).output(
NonZeroUsize::new(<CMain::ScalarExt as PrimeField>::NUM_BITS as usize).unwrap(),
);

let mut instances = self.sc.instances();
instances.insert(0, vec![marker, marker]);
instances
}

pub fn instances(&self, expected_out: C::ScalarExt) -> Vec<Vec<C::ScalarExt>> {
let input_marker = cyclefold::ro()
.absorb(&self.input)
.output(NonZeroUsize::new(<C::ScalarExt as PrimeField>::NUM_BITS as usize).unwrap());
pub fn instances(&self, expected_out: CMain::ScalarExt) -> Vec<Vec<CMain::ScalarExt>> {
let input_marker = cyclefold::ro().absorb(&self.input).output(
NonZeroUsize::new(<CMain::ScalarExt as PrimeField>::NUM_BITS as usize).unwrap(),
);

let mut instances = self.sc.instances();
instances.insert(0, vec![input_marker, expected_out]);
instances
}
}

impl<const ARITY: usize, C: CurveAffine, SC: StepCircuit<ARITY, C::ScalarExt>> Circuit<C::ScalarExt>
for StepFoldingCircuit<'_, ARITY, C, SC>
impl<
const ARITY: usize,
CMain: CurveAffine,
CSup: CurveAffine<Base = CMain::ScalarExt>,
SC: StepCircuit<ARITY, CMain::ScalarExt>,
> Circuit<CMain::ScalarExt> for StepFoldingCircuit<'_, ARITY, CMain, CSup, SC>
where
C::ScalarExt: PrimeFieldBits + FromUniformBytes<64>,
CMain::ScalarExt: PrimeFieldBits + FromUniformBytes<64>,
{
type Config = Config<SC::Config>;
type FloorPlanner = SimpleFloorPlanner;
Expand All @@ -81,10 +93,11 @@ where
Self {
sc: self.sc,
input: self.input.get_without_witness(),
_p: PhantomData,
}
}

fn configure(meta: &mut ConstraintSystem<C::ScalarExt>) -> Self::Config {
fn configure(meta: &mut ConstraintSystem<CMain::ScalarExt>) -> Self::Config {
Self::Config {
sc: SC::configure(meta),
mg: MainGate::configure(meta),
Expand All @@ -94,7 +107,7 @@ where
fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<C::ScalarExt>,
mut layouter: impl Layouter<CMain::ScalarExt>,
) -> Result<(), Halo2PlonkError> {
let input = layouter.assign_region(
|| "sfc input",
Expand All @@ -113,8 +126,8 @@ where
Halo2PlonkError::Synthesis
})?;

let _self_acc_out: input::assigned::ProtoGalaxyAccumulatorInstance<C::ScalarExt> = layouter
.assign_region(
let self_acc_out: input::assigned::ProtoGalaxyAccumulatorInstance<CMain::ScalarExt> =
layouter.assign_region(
|| "sfc protogalaxy",
|region| {
let mut region = RegionCtx::new(region, 0);
Expand All @@ -137,6 +150,18 @@ where
},
)?;

let paired_acc_out: input::assigned::SangriaAccumulatorInstance<CMain::ScalarExt> =
layouter.assign_region(
|| "sfc sangria",
|region| {
sangria_adapter::fold::<CMain, CSup>(
&mut RegionCtx::new(region, 0),
config.mg.clone(),
&input.paired_trace,
)
},
)?;

layouter.assign_region(
|| "sfc out",
|region| {
Expand All @@ -156,6 +181,24 @@ where
.try_into()
.unwrap();

let _self_trace_output =
input::assigned::ProtoGalaxyAccumulatorInstance::conditional_select(
&mut region,
&mg,
&input.self_trace.input_accumulator,
&self_acc_out,
&is_zero_step,
)?;

let _paired_trace_output =
input::assigned::SangriaAccumulatorInstance::conditional_select(
&mut region,
&mg,
&input.paired_trace.input_accumulator,
&paired_acc_out,
&is_zero_step,
);

Ok(())
},
)?;
Expand Down
Loading

0 comments on commit 3260960

Please sign in to comment.