use crate::bellman::pairing::{Engine, GenericCurveAffine, GenericCurveProjective};
use crate::bellman::pairing::ff::{BitIterator, Field, PrimeField, PrimeFieldRepr, ScalarEngine};
use crate::bellman::SynthesisError;
use num_bigint::BigUint;
use num_integer::Integer;
use num_traits::Num;
use crate::plonk::circuit::bigint::bigint::*;
#[derive(Clone, Debug)]
pub struct EndomorphismParameters<E: Engine> {
pub lambda: E::Fr,
pub beta_g1: <<E as Engine>::G1Affine as GenericCurveAffine>::Base,
pub a1: BigUint,
pub a2: BigUint,
pub minus_b1: BigUint,
pub b2: BigUint,
pub scalar_width: usize,
pub target_scalar_width: usize,
}
impl<E: Engine> EndomorphismParameters<E> {
pub fn calculate_decomposition(&self, val: E::Fr) -> (E::Fr, E::Fr) {
let value = repr_to_biguint::<E::Fr>(&val.into_repr());
let c1 = (&value * &self.a1) >> self.scalar_width;
let c2 = (&value * &self.a2) >> self.scalar_width;
let q1 = c1 * &self.minus_b1;
let q2 = c2 * &self.b2;
let q1 = biguint_to_repr::<E::Fr>(q1);
let q2 = biguint_to_repr::<E::Fr>(q2);
let q1 = E::Fr::from_repr(q1).unwrap();
let q2 = E::Fr::from_repr(q2).unwrap();
let mut k2 = q2;
k2.sub_assign(&q1);
let mut k1 = k2;
k1.mul_assign(&self.lambda);
k1.add_assign(&val);
(k1, k2)
}
pub fn apply_to_g1_point(&self, point: E::G1Affine) -> E::G1Affine {
let (mut x, mut y) = point.into_xy_unchecked();
y.negate();
x.mul_assign(&self.beta_g1);
debug_assert!(E::G1Affine::from_xy_checked(x, y).is_ok());
E::G1Affine::from_xy_unchecked(x, y)
}
}
pub fn bn254_endomorphism_parameters() -> EndomorphismParameters<crate::bellman::pairing::bn256::Bn256> {
let empty_fr_repr = crate::bellman::pairing::bn256::Fr::zero().into_repr();
let mut lambda_repr = empty_fr_repr;
lambda_repr.as_mut()[0] = 0x93e7cede4a0329b3;
lambda_repr.as_mut()[1] = 0x7d4fdca77a96c167;
lambda_repr.as_mut()[2] = 0x8be4ba08b19a750a;
lambda_repr.as_mut()[3] = 0x1cbd5653a5661c25;
let lambda = crate::bellman::pairing::bn256::Fr::from_raw_repr(lambda_repr).unwrap();
let mut may_be_one = lambda;
may_be_one.mul_assign(&lambda);
may_be_one.mul_assign(&lambda);
assert_eq!(may_be_one, crate::bellman::pairing::bn256::Fr::one());
let empty_fq_repr = crate::bellman::pairing::bn256::Fq::zero().into_repr();
let mut beta_g1_repr = empty_fq_repr;
beta_g1_repr.as_mut()[0] = 0x71930c11d782e155;
beta_g1_repr.as_mut()[1] = 0xa6bb947cffbe3323;
beta_g1_repr.as_mut()[2] = 0xaa303344d4741444;
beta_g1_repr.as_mut()[3] = 0x2c3b3f0d26594943;
let beta_g1 = crate::bellman::pairing::bn256::Fq::from_raw_repr(beta_g1_repr).unwrap();
let mut may_be_one = beta_g1;
may_be_one.mul_assign(&beta_g1);
may_be_one.mul_assign(&beta_g1);
assert_eq!(may_be_one, crate::bellman::pairing::bn256::Fq::one());
EndomorphismParameters::<crate::bellman::pairing::bn256::Bn256> {
lambda: lambda,
beta_g1: beta_g1,
a1: BigUint::from_str_radix("2d91d232ec7e0b3d7", 16).unwrap(),
a2: BigUint::from_str_radix("24ccef014a773d2cf7a7bd9d4391eb18d", 16).unwrap(),
minus_b1: BigUint::from_str_radix("6f4d8248eeb859fc8211bbeb7d4f1128", 16).unwrap(),
b2: BigUint::from_str_radix("89d3256894d213e3", 16).unwrap(),
scalar_width: 256,
target_scalar_width: 127,
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::bellman::pairing::*;
}