1use crate::{
2 short_weierstrass::{Affine, Projective, SWCurveConfig},
3 AdditiveGroup, CurveGroup,
4};
5use ark_ff::{PrimeField, Zero};
6use ark_std::ops::Neg;
7use num_bigint::{BigInt, BigUint, Sign};
8use num_integer::Integer;
9use num_traits::{One, Signed};
10
11pub trait GLVConfig: Send + Sync + 'static + SWCurveConfig {
13 const ENDO_COEFFS: &[Self::BaseField];
17
18 const LAMBDA: Self::ScalarField;
22
23 const SCALAR_DECOMP_COEFFS: [(bool, <Self::ScalarField as PrimeField>::BigInt); 4];
27
28 fn scalar_decomposition(
30 k: Self::ScalarField,
31 ) -> ((bool, Self::ScalarField), (bool, Self::ScalarField)) {
32 let scalar: BigInt = k.into_bigint().into().into();
33
34 let [n11, n12, n21, n22] = Self::SCALAR_DECOMP_COEFFS.map(|x| {
35 let sign = if x.0 { Sign::Plus } else { Sign::Minus };
36 BigInt::from_biguint(sign, x.1.into())
37 });
38
39 let r = BigInt::from(Self::ScalarField::MODULUS.into());
40
41 let beta_1 = {
46 let (mut div, rem) = (&scalar * &n22).div_rem(&r);
47 if (&rem + &rem) > r {
48 div += BigInt::one();
49 }
50 div
51 };
52 let beta_2 = {
53 let (mut div, rem) = (&scalar * &n12.clone().neg()).div_rem(&r);
54 if (&rem + &rem) > r {
55 div += BigInt::one();
56 }
57 div
58 };
59
60 let b11 = &beta_1 * &n11;
66 let b12 = &beta_2 * &n21;
67 let b1 = b11 + b12;
68
69 let b21 = &beta_1 * &n12;
71 let b22 = &beta_2 * &n22;
72 let b2 = b21 + b22;
73
74 let k1 = &scalar - b1;
75 let k1_abs = BigUint::try_from(k1.abs()).unwrap();
76
77 let k2 = -b2;
79 let k2_abs = BigUint::try_from(k2.abs()).unwrap();
80
81 (
82 (k1.sign() == Sign::Plus, k1_abs.into()),
83 (k2.sign() == Sign::Plus, k2_abs.into()),
84 )
85 }
86
87 fn endomorphism(p: &Projective<Self>) -> Projective<Self>;
88
89 fn endomorphism_affine(p: &Affine<Self>) -> Affine<Self>;
90
91 fn glv_mul_projective(p: Projective<Self>, k: Self::ScalarField) -> Projective<Self> {
92 let ((sgn_k1, k1), (sgn_k2, k2)) = Self::scalar_decomposition(k);
93
94 let mut b1 = p;
95 let mut b2 = Self::endomorphism(&p);
96
97 if !sgn_k1 {
98 b1 = -b1;
99 }
100 if !sgn_k2 {
101 b2 = -b2;
102 }
103
104 let b1b2 = b1 + b2;
105
106 let iter_k1 = ark_ff::BitIteratorBE::new(k1.into_bigint());
107 let iter_k2 = ark_ff::BitIteratorBE::new(k2.into_bigint());
108
109 let mut res = Projective::zero();
110 let mut skip_zeros = true;
111 for pair in iter_k1.zip(iter_k2) {
112 if skip_zeros {
113 if pair == (false, false) {
114 continue;
115 }
116 skip_zeros = false;
117 }
118 res.double_in_place();
119 match pair {
120 (true, false) => res += b1,
121 (false, true) => res += b2,
122 (true, true) => res += b1b2,
123 (false, false) => {},
124 }
125 }
126 res
127 }
128
129 fn glv_mul_affine(p: Affine<Self>, k: Self::ScalarField) -> Affine<Self> {
130 let ((sgn_k1, k1), (sgn_k2, k2)) = Self::scalar_decomposition(k);
131
132 let mut b1 = p;
133 let mut b2 = Self::endomorphism_affine(&p);
134
135 if !sgn_k1 {
136 b1 = -b1;
137 }
138 if !sgn_k2 {
139 b2 = -b2;
140 }
141
142 let b1b2 = b1 + b2;
143
144 let iter_k1 = ark_ff::BitIteratorBE::new(k1.into_bigint());
145 let iter_k2 = ark_ff::BitIteratorBE::new(k2.into_bigint());
146
147 let mut res = Projective::zero();
148 let mut skip_zeros = true;
149 for pair in iter_k1.zip(iter_k2) {
150 if skip_zeros {
151 if pair == (false, false) {
152 continue;
153 }
154 skip_zeros = false;
155 }
156 res.double_in_place();
157 match pair {
158 (true, false) => res += b1,
159 (false, true) => res += b2,
160 (true, true) => res += b1b2,
161 (false, false) => {},
162 }
163 }
164 res.into_affine()
165 }
166}