arnaucube
arnaucube/sonobePublic Self-hosted repository
sonobe/src/folding/circuits/nonnative.rs
src/folding/circuits/nonnative.rsRaw
  1use ark_ec::{AffineRepr, CurveGroup};
  2use ark_ff::PrimeField;
  3use ark_r1cs_std::fields::nonnative::{params::OptimizationType, AllocatedNonNativeFieldVar};
  4use ark_r1cs_std::{
  5    alloc::{AllocVar, AllocationMode},
  6    fields::{fp::FpVar, nonnative::NonNativeFieldVar},
  7    ToConstraintFieldGadget,
  8};
  9use ark_relations::r1cs::{Namespace, SynthesisError};
 10use ark_std::{One, Zero};
 11use core::borrow::Borrow;
 12
 13/// NonNativeAffineVar represents an elliptic curve point in Affine represenation in the non-native
 14/// field, over the constraint field. It is not intended to perform operations, but just to contain
 15/// the affine coordinates in order to perform hash operations of the point.
 16#[derive(Debug, Clone)]
 17pub struct NonNativeAffineVar<F: PrimeField> {
 18    pub x: Vec<FpVar<F>>,
 19    pub y: Vec<FpVar<F>>,
 20}
 21
 22impl<C> AllocVar<C, C::ScalarField> for NonNativeAffineVar<C::ScalarField>
 23where
 24    C: CurveGroup,
 25    <C as ark_ec::CurveGroup>::BaseField: ark_ff::PrimeField,
 26{
 27    fn new_variable<T: Borrow<C>>(
 28        cs: impl Into<Namespace<C::ScalarField>>,
 29        f: impl FnOnce() -> Result<T, SynthesisError>,
 30        mode: AllocationMode,
 31    ) -> Result<Self, SynthesisError> {
 32        f().and_then(|val| {
 33            let cs = cs.into();
 34
 35            let affine = val.borrow().into_affine();
 36            let xy_obj = &affine.xy();
 37            let mut xy = (&C::BaseField::zero(), &C::BaseField::one());
 38            if xy_obj.is_some() {
 39                xy = xy_obj.unwrap();
 40            }
 41            let x = NonNativeFieldVar::<C::BaseField, C::ScalarField>::new_variable(
 42                cs.clone(),
 43                || Ok(xy.0),
 44                mode,
 45            )?
 46            .to_constraint_field()?;
 47            let y = NonNativeFieldVar::<C::BaseField, C::ScalarField>::new_variable(
 48                cs.clone(),
 49                || Ok(xy.1),
 50                mode,
 51            )?
 52            .to_constraint_field()?;
 53
 54            Ok(Self { x, y })
 55        })
 56    }
 57}
 58
 59/// point_to_nonnative_limbs is used to return (outside the circuit) the limbs representation that
 60/// matches the one used in-circuit.
 61#[allow(clippy::type_complexity)]
 62pub fn point_to_nonnative_limbs<C: CurveGroup>(
 63    p: C,
 64) -> Result<(Vec<C::ScalarField>, Vec<C::ScalarField>), SynthesisError>
 65where
 66    <C as ark_ec::CurveGroup>::BaseField: ark_ff::PrimeField,
 67{
 68    let affine = p.into_affine();
 69    if affine.is_zero() {
 70        let x =
 71            AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
 72                &C::BaseField::zero(),
 73                OptimizationType::Weight,
 74            )?;
 75        let y =
 76            AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
 77                &C::BaseField::one(),
 78                OptimizationType::Weight,
 79            )?;
 80        return Ok((x, y));
 81    }
 82
 83    let (x, y) = affine.xy().unwrap();
 84    let x = AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
 85        x,
 86        OptimizationType::Weight,
 87    )?;
 88    let y = AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
 89        y,
 90        OptimizationType::Weight,
 91    )?;
 92    Ok((x, y))
 93}
 94
 95#[cfg(test)]
 96mod tests {
 97    use super::*;
 98    use ark_pallas::{Fr, Projective};
 99    use ark_r1cs_std::alloc::AllocVar;
100    use ark_relations::r1cs::ConstraintSystem;
101    use ark_std::Zero;
102
103    #[test]
104    fn test_alloc_nonnativeaffinevar_zero() {
105        let cs = ConstraintSystem::<Fr>::new_ref();
106
107        // dealing with the 'zero' point should not panic when doing the unwrap
108        let p = Projective::zero();
109        NonNativeAffineVar::<Fr>::new_witness(cs.clone(), || Ok(p)).unwrap();
110    }
111}