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::nonnative::NonNativeFieldVar,
7};
8use ark_relations::r1cs::{Namespace, SynthesisError};
9use core::borrow::Borrow;
10
11/// NonNativeAffineVar represents an elliptic curve point in Affine represenation in the non-native
12/// field. It is not intended to perform operations, but just to contain the affine coordinates in
13/// order to perform hash operations of the point.
14#[derive(Debug, Clone)]
15pub struct NonNativeAffineVar<F: PrimeField, CF: PrimeField> {
16 pub x: NonNativeFieldVar<F, CF>,
17 pub y: NonNativeFieldVar<F, CF>,
18}
19
20impl<C> AllocVar<C, C::ScalarField> for NonNativeAffineVar<C::BaseField, C::ScalarField>
21where
22 C: CurveGroup,
23 <C as ark_ec::CurveGroup>::BaseField: ark_ff::PrimeField,
24{
25 fn new_variable<T: Borrow<C>>(
26 cs: impl Into<Namespace<C::ScalarField>>,
27 f: impl FnOnce() -> Result<T, SynthesisError>,
28 mode: AllocationMode,
29 ) -> Result<Self, SynthesisError> {
30 f().and_then(|val| {
31 let cs = cs.into();
32
33 let affine = val.borrow().into_affine();
34 let xy = affine.xy().unwrap();
35 let x = NonNativeFieldVar::<C::BaseField, C::ScalarField>::new_variable(
36 cs.clone(),
37 || Ok(xy.0),
38 mode,
39 )?;
40 let y = NonNativeFieldVar::<C::BaseField, C::ScalarField>::new_variable(
41 cs.clone(),
42 || Ok(xy.1),
43 mode,
44 )?;
45
46 Ok(Self { x, y })
47 })
48 }
49}
50
51/// point_to_nonnative_limbs is used to return (outside the circuit) the limbs representation that
52/// matches the one used in-circuit.
53#[allow(clippy::type_complexity)]
54pub fn point_to_nonnative_limbs<C: CurveGroup>(
55 p: C,
56) -> Result<(Vec<C::ScalarField>, Vec<C::ScalarField>), SynthesisError>
57where
58 <C as ark_ec::CurveGroup>::BaseField: ark_ff::PrimeField,
59{
60 let affine = p.into_affine();
61 let (x, y) = affine.xy().unwrap();
62 let x = AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
63 x,
64 OptimizationType::Weight,
65 )?;
66 let y = AllocatedNonNativeFieldVar::<C::BaseField, C::ScalarField>::get_limbs_representations(
67 y,
68 OptimizationType::Weight,
69 )?;
70 Ok((x, y))
71}