Skip to content

Commit

Permalink
feat(ivc): cyclefold::sfc ro_absorb
Browse files Browse the repository at this point in the history
**Motivation**
Within #369 and cyclfold in general we need to count consistency markers, for this we need to be able to absorb sfc::input

**Overview**
Just implementation of `AbsorbInRO` trait for all sfc::input types
  • Loading branch information
cyphersnake committed Dec 3, 2024
1 parent 4a13a9d commit d8b460e
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 14 deletions.
40 changes: 35 additions & 5 deletions src/gadgets/nonnative/bn/big_uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ use num_bigint::BigUint as BigUintRaw;
use num_traits::{identities::One, Zero};
use tracing::*;

use crate::{error::Halo2PlonkError, ff::PrimeField, main_gate::RegionCtx};
use crate::{
error::Halo2PlonkError,
ff::PrimeField,
main_gate::RegionCtx,
poseidon::{AbsorbInRO, ROTrait},
};

// A big natural number with limbs in field `F`
//
Expand Down Expand Up @@ -41,6 +46,12 @@ impl<F: PrimeField> BigUint<F> {
}
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for BigUint<F> {
fn absorb_into(&self, ro: &mut RO) {
ro.absorb_field_iter(self.limbs().iter().copied());
}
}

#[derive(thiserror::Error, Debug, PartialEq, Eq)]
pub enum Error {
// Too big bigint: try to increase the number of limbs or their width
Expand Down Expand Up @@ -198,11 +209,15 @@ impl<F: PrimeField> BigUint<F> {
}

pub fn from_different_field<D: PrimeField>(
_input: &D,
_limb_width: NonZeroUsize,
_n_limbs: NonZeroUsize,
input: &D,
limb_width: NonZeroUsize,
n_limbs: NonZeroUsize,
) -> Result<Self, Error> {
todo!("Implement and test the conversion of an element from another field")
Self::from_biguint(
&BigUintRaw::from_bytes_le(input.to_repr().as_ref()),
limb_width,
n_limbs,
)
}

pub fn into_bigint(&self) -> num_bigint::BigUint {
Expand Down Expand Up @@ -300,6 +315,7 @@ fn get_max_word_mask_bits(limb_width: usize) -> usize {
mod tests {
use std::mem;

use halo2_proofs::halo2curves::pasta::Fq;
use tracing_test::traced_test;

use super::*;
Expand Down Expand Up @@ -397,4 +413,18 @@ mod tests {
})
);
}

#[traced_test]
#[test]
fn from_diff_field() {
let input = Fq::from_u128(u64::MAX as u128 * 2);

let limbs_count = NonZeroUsize::new(50).unwrap();
let _result_with_bn = BigUint::<Fp>::from_different_field(
&input,
NonZeroUsize::new(10).unwrap(),
limbs_count,
)
.unwrap();
}
}
14 changes: 13 additions & 1 deletion src/ivc/cyclefold/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::num::NonZeroUsize;

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

use crate::poseidon::{PoseidonHash, ROTrait, Spec};
Expand All @@ -14,6 +16,16 @@ pub const RATE: usize = T - 1;
pub const R_F: usize = 10;
pub const R_P: usize = 10;

/// Safety: because 32 != 0
pub const DEFAULT_LIMB_WIDTH: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(32) };

/// Safety: because 10 != 0
pub const DEFAULT_LIMBS_COUNT_LIMIT: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(10) };

pub fn ro_const<F: PrimeFieldBits + FromUniformBytes<64>>() -> Spec<F, T, RATE> {
Spec::<F, T, RATE>::new(R_F, R_P)
}

pub fn ro<F: PrimeFieldBits + FromUniformBytes<64>>() -> PoseidonHash<F, T, RATE> {
PoseidonHash::<F, T, RATE>::new(Spec::<F, T, RATE>::new(R_F, R_P))
PoseidonHash::<F, T, RATE>::new(ro_const())
}
126 changes: 122 additions & 4 deletions src/ivc/cyclefold/sfc/input.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::array;

use super::super::{DEFAULT_LIMBS_COUNT_LIMIT, DEFAULT_LIMB_WIDTH};
use crate::{
gadgets::nonnative::bn::big_uint::BigUint,
halo2_proofs::halo2curves::{ff::PrimeField, CurveAffine},
nifs, plonk,
polynomial::univariate::UnivariatePoly,
prelude::{DEFAULT_LIMBS_COUNT_LIMIT, DEFAULT_LIMB_WIDTH},
poseidon::{AbsorbInRO, ROTrait},
};

#[derive(Clone)]
Expand All @@ -14,15 +15,30 @@ pub struct BigUintPoint<F: PrimeField> {
y: BigUint<F>,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for BigUintPoint<F> {
fn absorb_into(&self, ro: &mut RO) {
ro.absorb_field_iter(self.x.limbs().iter().chain(self.y.limbs().iter()).cloned());
}
}

impl<C: CurveAffine> From<&C> for BigUintPoint<C::ScalarExt> {
fn from(_value: &C) -> Self {
todo!()
fn from(value: &C) -> Self {
let c = value.coordinates().unwrap();
Self {
x: BigUint::from_different_field(c.x(), DEFAULT_LIMB_WIDTH, DEFAULT_LIMBS_COUNT_LIMIT)
.unwrap(),
y: BigUint::from_different_field(c.y(), DEFAULT_LIMB_WIDTH, DEFAULT_LIMBS_COUNT_LIMIT)
.unwrap(),
}
}
}

impl<F: PrimeField> BigUintPoint<F> {
fn identity() -> Self {
todo!()
Self {
x: BigUint::zero(DEFAULT_LIMB_WIDTH),
y: BigUint::zero(DEFAULT_LIMB_WIDTH),
}
}
}

Expand All @@ -33,13 +49,40 @@ pub struct NativePlonkInstance<F: PrimeField> {
pub(crate) challenges: Vec<F>,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for NativePlonkInstance<F> {
fn absorb_into(&self, ro: &mut RO) {
let Self {
W_commitments,
instances,
challenges,
} = self;
ro.absorb_iter(W_commitments.iter())
.absorb_field_iter(instances.iter().flatten().cloned())
.absorb_field_iter(challenges.iter().cloned());
}
}

#[derive(Clone)]
pub struct PairedPlonkInstance<F: PrimeField> {
pub(crate) W_commitments: Vec<(F, F)>,
pub(crate) instances: Vec<Vec<BigUint<F>>>,
pub(crate) challenges: Vec<BigUint<F>>,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for PairedPlonkInstance<F> {
fn absorb_into(&self, ro: &mut RO) {
let Self {
W_commitments,
instances,
challenges,
} = self;

ro.absorb_field_iter(W_commitments.iter().flat_map(|(x, y)| [x, y]).copied())
.absorb_iter(instances.iter().flatten())
.absorb_iter(challenges.iter());
}
}

impl<C: CurveAffine> From<plonk::PlonkInstance<C>> for NativePlonkInstance<C::ScalarExt> {
fn from(value: plonk::PlonkInstance<C>) -> Self {
Self {
Expand All @@ -57,13 +100,39 @@ pub struct ProtoGalaxyAccumulatorInstance<F: PrimeField> {
pub(crate) e: F,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for ProtoGalaxyAccumulatorInstance<F> {
fn absorb_into(&self, ro: &mut RO) {
let Self { ins, betas, e } = self;

ro.absorb(ins)
.absorb_field_iter(betas.iter().cloned())
.absorb_field(*e);
}
}

/// Recursive trace of the circuit itself
pub struct SelfTrace<F: PrimeField> {
pub input_accumulator: ProtoGalaxyAccumulatorInstance<F>,
pub incoming: NativePlonkInstance<F>,
pub proof: nifs::protogalaxy::Proof<F>,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for SelfTrace<F> {
fn absorb_into(&self, ro: &mut RO) {
let Self {
input_accumulator,
incoming,
proof,
} = self;

let nifs::protogalaxy::Proof { poly_F, poly_K } = proof;

ro.absorb(input_accumulator)
.absorb(incoming)
.absorb_field_iter(poly_K.iter().chain(poly_F.iter()).copied());
}
}

impl<F: PrimeField> SelfTrace<F> {
pub fn new_initial(native_plonk_structure: &plonk::PlonkStructure<F>) -> Self {
// SPS protocol setup
Expand Down Expand Up @@ -114,6 +183,18 @@ pub struct SangriaAccumulatorInstance<F: PrimeField> {
pub(crate) u: BigUint<F>,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for SangriaAccumulatorInstance<F> {
fn absorb_into(&self, ro: &mut RO) {
let Self {
ins,
E_commitment: (ex, ey),
u,
} = self;

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

pub struct PairedTrace<F: PrimeField> {
pub input_accumulator: SangriaAccumulatorInstance<F>,
// The size from one to three
Expand All @@ -122,6 +203,22 @@ pub struct PairedTrace<F: PrimeField> {
proof: nifs::sangria::CrossTermCommits<(F, F)>,
}

impl<F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for PairedTrace<F> {
fn absorb_into(&self, ro: &mut RO) {
let Self {
input_accumulator,
incoming,
proof,
} = self;

let proof_iter = proof.iter().flat_map(|(a, b)| [a, b]).copied();

ro.absorb(input_accumulator)
.absorb_iter(incoming.iter())
.absorb_field_iter(proof_iter);
}
}

impl<F: PrimeField> PairedTrace<F> {
pub fn new_initial<CSup: CurveAffine<Base = F>>(
paired_plonk_structure: &plonk::PlonkStructure<CSup::ScalarExt>,
Expand Down Expand Up @@ -203,6 +300,27 @@ pub struct Input<const ARITY: usize, F: PrimeField> {
pub z_i: [F; ARITY],
}

impl<const ARITY: usize, F: PrimeField, RO: ROTrait<F>> AbsorbInRO<F, RO> for Input<ARITY, F> {
fn absorb_into(&self, ro: &mut RO) {
let Self {
pp_digest: (pp0, pp1),
self_trace,
paired_trace,
step,
z_0,
z_i,
} = self;

ro.absorb_field(*pp0)
.absorb_field(*pp1)
.absorb(self_trace)
.absorb(paired_trace)
.absorb_field(F::from(*step as u64))
.absorb_field_iter(z_0.iter().copied())
.absorb_field_iter(z_i.iter().copied());
}
}

impl<const ARITY: usize, F: PrimeField> Input<ARITY, F> {
pub(super) fn get_without_witness(&self) -> Self {
todo!()
Expand Down
4 changes: 0 additions & 4 deletions src/ivc/cyclefold/sfc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ pub struct StepFoldingCircuit<
pub input: Input<ARITY, C::ScalarExt>,
}

pub fn instances_lens() -> Box<[usize]> {
todo!()
}

impl<'sc, const ARITY: usize, C: CurveAffine, SC: StepCircuit<ARITY, C::ScalarExt>>
StepFoldingCircuit<'sc, ARITY, C, SC>
{
Expand Down

0 comments on commit d8b460e

Please sign in to comment.