1use crate::{
2 env::internal::{self, BytesObject, U256Val, U64Val},
3 impl_bytesn_repr,
4 unwrap::{UnwrapInfallible, UnwrapOptimized},
5 Bytes, BytesN, ConversionError, Env, IntoVal, TryFromVal, Val, Vec, U256,
6};
7use core::{
8 cmp::Ordering,
9 fmt::Debug,
10 ops::{Add, Mul, Sub},
11};
12
13pub struct Bls12_381 {
16 env: Env,
17}
18
19#[derive(Clone)]
46#[repr(transparent)]
47pub struct G1Affine(BytesN<96>);
48
49#[derive(Clone)]
66#[repr(transparent)]
67pub struct G2Affine(BytesN<192>);
68
69#[derive(Clone)]
76#[repr(transparent)]
77pub struct Fp(BytesN<48>);
78
79#[derive(Clone)]
88#[repr(transparent)]
89pub struct Fp2(BytesN<96>);
90
91#[derive(Clone)]
96#[repr(transparent)]
97pub struct Fr(U256);
98
99impl_bytesn_repr!(G1Affine, 96);
100impl_bytesn_repr!(G2Affine, 192);
101impl_bytesn_repr!(Fp, 48);
102impl_bytesn_repr!(Fp2, 96);
103
104impl G1Affine {
105 pub fn env(&self) -> &Env {
106 self.0.env()
107 }
108
109 pub fn is_in_subgroup(&self) -> bool {
110 self.env().crypto().bls12_381().g1_is_in_subgroup(self)
111 }
112
113 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
114 self.env().crypto().bls12_381().g1_checked_add(self, rhs)
115 }
116}
117
118impl Add for G1Affine {
119 type Output = G1Affine;
120
121 fn add(self, rhs: Self) -> Self::Output {
122 self.env().crypto().bls12_381().g1_add(&self, &rhs)
123 }
124}
125
126impl Mul<Fr> for G1Affine {
127 type Output = G1Affine;
128
129 fn mul(self, rhs: Fr) -> Self::Output {
130 self.env().crypto().bls12_381().g1_mul(&self, &rhs)
131 }
132}
133
134impl G2Affine {
135 pub fn env(&self) -> &Env {
136 self.0.env()
137 }
138
139 pub fn is_in_subgroup(&self) -> bool {
140 self.env().crypto().bls12_381().g2_is_in_subgroup(self)
141 }
142
143 pub fn checked_add(&self, rhs: &Self) -> Option<Self> {
144 self.env().crypto().bls12_381().g2_checked_add(self, rhs)
145 }
146}
147
148impl Add for G2Affine {
149 type Output = G2Affine;
150
151 fn add(self, rhs: Self) -> Self::Output {
152 self.env().crypto().bls12_381().g2_add(&self, &rhs)
153 }
154}
155
156impl Mul<Fr> for G2Affine {
157 type Output = G2Affine;
158
159 fn mul(self, rhs: Fr) -> Self::Output {
160 self.env().crypto().bls12_381().g2_mul(&self, &rhs)
161 }
162}
163
164impl Fp {
165 pub fn env(&self) -> &Env {
166 self.0.env()
167 }
168
169 pub fn map_to_g1(&self) -> G1Affine {
170 self.env().crypto().bls12_381().map_fp_to_g1(self)
171 }
172}
173
174impl Fp2 {
175 pub fn env(&self) -> &Env {
176 self.0.env()
177 }
178
179 pub fn map_to_g2(&self) -> G2Affine {
180 self.env().crypto().bls12_381().map_fp2_to_g2(self)
181 }
182}
183
184impl Fr {
185 pub fn env(&self) -> &Env {
186 self.0.env()
187 }
188
189 pub fn from_u256(value: U256) -> Self {
190 value.into()
191 }
192
193 pub fn to_u256(&self) -> U256 {
194 self.0.clone()
195 }
196
197 pub fn as_u256(&self) -> &U256 {
198 &self.0
199 }
200
201 pub fn from_bytes(bytes: BytesN<32>) -> Self {
202 U256::from_be_bytes(bytes.env(), bytes.as_ref()).into()
203 }
204
205 pub fn to_bytes(&self) -> BytesN<32> {
206 self.as_u256().to_be_bytes().try_into().unwrap_optimized()
207 }
208
209 pub fn as_val(&self) -> &Val {
210 self.0.as_val()
211 }
212
213 pub fn to_val(&self) -> Val {
214 self.0.to_val()
215 }
216
217 pub fn pow(&self, rhs: u64) -> Self {
218 self.env().crypto().bls12_381().fr_pow(self, rhs)
219 }
220
221 pub fn inv(&self) -> Self {
222 self.env().crypto().bls12_381().fr_inv(self)
223 }
224}
225
226impl From<U256> for Fr {
227 fn from(value: U256) -> Self {
228 Self(value)
229 }
230}
231
232impl From<&Fr> for U256Val {
233 fn from(value: &Fr) -> Self {
234 value.as_u256().into()
235 }
236}
237
238impl IntoVal<Env, Val> for Fr {
239 fn into_val(&self, e: &Env) -> Val {
240 self.0.into_val(e)
241 }
242}
243
244impl TryFromVal<Env, Val> for Fr {
245 type Error = ConversionError;
246
247 fn try_from_val(env: &Env, val: &Val) -> Result<Self, Self::Error> {
248 let u = U256::try_from_val(env, val)?;
249 Ok(Fr(u))
250 }
251}
252
253impl Eq for Fr {}
254
255impl PartialEq for Fr {
256 fn eq(&self, other: &Self) -> bool {
257 self.as_u256().partial_cmp(other.as_u256()) == Some(Ordering::Equal)
258 }
259}
260
261impl Debug for Fr {
262 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
263 write!(f, "Fr({:?})", self.as_u256())
264 }
265}
266
267impl Add for Fr {
268 type Output = Fr;
269
270 fn add(self, rhs: Self) -> Self::Output {
271 self.env().crypto().bls12_381().fr_add(&self, &rhs)
272 }
273}
274
275impl Sub for Fr {
276 type Output = Fr;
277
278 fn sub(self, rhs: Self) -> Self::Output {
279 self.env().crypto().bls12_381().fr_sub(&self, &rhs)
280 }
281}
282
283impl Mul for Fr {
284 type Output = Fr;
285
286 fn mul(self, rhs: Self) -> Self::Output {
287 self.env().crypto().bls12_381().fr_mul(&self, &rhs)
288 }
289}
290
291impl Bls12_381 {
292 pub(crate) fn new(env: &Env) -> Bls12_381 {
293 Bls12_381 { env: env.clone() }
294 }
295
296 pub fn env(&self) -> &Env {
297 &self.env
298 }
299
300 pub fn g1_is_in_subgroup(&self, p: &G1Affine) -> bool {
304 let env = self.env();
305 let res = internal::Env::bls12_381_check_g1_is_in_subgroup(env, p.to_object())
306 .unwrap_infallible();
307 res.into()
308 }
309
310 pub fn g1_add(&self, p0: &G1Affine, p1: &G1Affine) -> G1Affine {
312 let env = self.env();
313 let bin = internal::Env::bls12_381_g1_add(env, p0.to_object(), p1.to_object())
314 .unwrap_infallible();
315 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
316 }
317
318 pub fn g1_checked_add(&self, p0: &G1Affine, p1: &G1Affine) -> Option<G1Affine> {
324 let env = self.env();
325 let bin = internal::Env::bls12_381_g1_add(env, p0.to_object(), p1.to_object())
326 .unwrap_infallible();
327 let res = unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) };
328 let is_in_correct_subgroup: bool =
329 internal::Env::bls12_381_check_g1_is_in_subgroup(env, res.to_object())
330 .unwrap_optimized()
331 .into();
332 match is_in_correct_subgroup {
333 true => Some(res),
334 false => None,
335 }
336 }
337
338 pub fn g1_mul(&self, p0: &G1Affine, scalar: &Fr) -> G1Affine {
340 let env = self.env();
341 let bin =
342 internal::Env::bls12_381_g1_mul(env, p0.to_object(), scalar.into()).unwrap_infallible();
343 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
344 }
345
346 pub fn g1_msm(&self, vp: Vec<G1Affine>, vs: Vec<Fr>) -> G1Affine {
348 let env = self.env();
349 let bin = internal::Env::bls12_381_g1_msm(env, vp.into(), vs.into()).unwrap_infallible();
350 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
351 }
352
353 pub fn map_fp_to_g1(&self, fp: &Fp) -> G1Affine {
355 let env = self.env();
356 let bin = internal::Env::bls12_381_map_fp_to_g1(env, fp.to_object()).unwrap_infallible();
357 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
358 }
359
360 pub fn hash_to_g1(&self, msg: &Bytes, dst: &Bytes) -> G1Affine {
362 let env = self.env();
363 let bin = internal::Env::bls12_381_hash_to_g1(env, msg.into(), dst.to_object())
364 .unwrap_infallible();
365 unsafe { G1Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
366 }
367
368 pub fn g2_is_in_subgroup(&self, p: &G2Affine) -> bool {
372 let env = self.env();
373 let res = internal::Env::bls12_381_check_g2_is_in_subgroup(env, p.to_object())
374 .unwrap_infallible();
375 res.into()
376 }
377
378 pub fn g2_add(&self, p0: &G2Affine, p1: &G2Affine) -> G2Affine {
380 let env = self.env();
381 let bin = internal::Env::bls12_381_g2_add(env, p0.to_object(), p1.to_object())
382 .unwrap_infallible();
383 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
384 }
385
386 pub fn g2_checked_add(&self, p0: &G2Affine, p1: &G2Affine) -> Option<G2Affine> {
392 let env = self.env();
393 let bin = internal::Env::bls12_381_g2_add(env, p0.to_object(), p1.to_object())
394 .unwrap_infallible();
395 let res = unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) };
396 let is_in_correct_subgroup: bool =
397 internal::Env::bls12_381_check_g2_is_in_subgroup(env, res.to_object())
398 .unwrap_optimized()
399 .into();
400 match is_in_correct_subgroup {
401 true => Some(res),
402 false => None,
403 }
404 }
405
406 pub fn g2_mul(&self, p0: &G2Affine, scalar: &Fr) -> G2Affine {
408 let env = self.env();
409 let bin =
410 internal::Env::bls12_381_g2_mul(env, p0.to_object(), scalar.into()).unwrap_infallible();
411 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
412 }
413
414 pub fn g2_msm(&self, vp: Vec<G2Affine>, vs: Vec<Fr>) -> G2Affine {
416 let env = self.env();
417 let bin = internal::Env::bls12_381_g2_msm(env, vp.into(), vs.into()).unwrap_infallible();
418 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
419 }
420
421 pub fn map_fp2_to_g2(&self, fp2: &Fp2) -> G2Affine {
423 let env = self.env();
424 let bin = internal::Env::bls12_381_map_fp2_to_g2(env, fp2.to_object()).unwrap_infallible();
425 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
426 }
427
428 pub fn hash_to_g2(&self, msg: &Bytes, dst: &Bytes) -> G2Affine {
430 let env = self.env();
431 let bin = internal::Env::bls12_381_hash_to_g2(env, msg.into(), dst.to_object())
432 .unwrap_infallible();
433 unsafe { G2Affine::from_bytes(BytesN::unchecked_new(env.clone(), bin)) }
434 }
435
436 pub fn pairing_check(&self, vp1: Vec<G1Affine>, vp2: Vec<G2Affine>) -> bool {
451 let env = self.env();
452 internal::Env::bls12_381_multi_pairing_check(env, vp1.into(), vp2.into())
453 .unwrap_infallible()
454 .into()
455 }
456
457 pub fn fr_add(&self, lhs: &Fr, rhs: &Fr) -> Fr {
461 let env = self.env();
462 let v = internal::Env::bls12_381_fr_add(env, lhs.into(), rhs.into()).unwrap_infallible();
463 U256::try_from_val(env, &v).unwrap_infallible().into()
464 }
465
466 pub fn fr_sub(&self, lhs: &Fr, rhs: &Fr) -> Fr {
468 let env = self.env();
469 let v = internal::Env::bls12_381_fr_sub(env, lhs.into(), rhs.into()).unwrap_infallible();
470 U256::try_from_val(env, &v).unwrap_infallible().into()
471 }
472
473 pub fn fr_mul(&self, lhs: &Fr, rhs: &Fr) -> Fr {
475 let env = self.env();
476 let v = internal::Env::bls12_381_fr_mul(env, lhs.into(), rhs.into()).unwrap_infallible();
477 U256::try_from_val(env, &v).unwrap_infallible().into()
478 }
479
480 pub fn fr_pow(&self, lhs: &Fr, rhs: u64) -> Fr {
482 let env = self.env();
483 let rhs = U64Val::try_from_val(env, &rhs).unwrap_optimized();
484 let v = internal::Env::bls12_381_fr_pow(env, lhs.into(), rhs).unwrap_infallible();
485 U256::try_from_val(env, &v).unwrap_infallible().into()
486 }
487
488 pub fn fr_inv(&self, lhs: &Fr) -> Fr {
490 let env = self.env();
491 let v = internal::Env::bls12_381_fr_inv(env, lhs.into()).unwrap_infallible();
492 U256::try_from_val(env, &v).unwrap_infallible().into()
493 }
494}