use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::PrimeField; use ark_r1cs_std::fields::nonnative::{params::OptimizationType, AllocatedNonNativeFieldVar}; use ark_r1cs_std::{ alloc::{AllocVar, AllocationMode}, fields::nonnative::NonNativeFieldVar, }; use ark_relations::r1cs::{Namespace, SynthesisError}; use core::borrow::Borrow; /// NonNativeAffineVar represents an elliptic curve point in Affine represenation in the non-native /// field. It is not intended to perform operations, but just to contain the affine coordinates in /// order to perform hash operations of the point. #[derive(Debug, Clone)] pub struct NonNativeAffineVar { pub x: NonNativeFieldVar, pub y: NonNativeFieldVar, } impl AllocVar for NonNativeAffineVar where C: CurveGroup, ::BaseField: ark_ff::PrimeField, { fn new_variable>( cs: impl Into>, f: impl FnOnce() -> Result, mode: AllocationMode, ) -> Result { f().and_then(|val| { let cs = cs.into(); let affine = val.borrow().into_affine(); let xy = affine.xy().unwrap(); let x = NonNativeFieldVar::::new_variable( cs.clone(), || Ok(xy.0), mode, )?; let y = NonNativeFieldVar::::new_variable( cs.clone(), || Ok(xy.1), mode, )?; Ok(Self { x, y }) }) } } /// point_to_nonnative_limbs is used to return (outside the circuit) the limbs representation that /// matches the one used in-circuit. #[allow(clippy::type_complexity)] pub fn point_to_nonnative_limbs( p: C, ) -> Result<(Vec, Vec), SynthesisError> where ::BaseField: ark_ff::PrimeField, { let affine = p.into_affine(); let (x, y) = affine.xy().unwrap(); let x = AllocatedNonNativeFieldVar::::get_limbs_representations( x, OptimizationType::Weight, )?; let y = AllocatedNonNativeFieldVar::::get_limbs_representations( y, OptimizationType::Weight, )?; Ok((x, y)) }