Skip to content

Commit d5ca355

Browse files
Revert "Remove pairing guest library and tests (moved to new repo)"
This reverts commit 27e82aa.
1 parent c93660e commit d5ca355

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+5425
-0
lines changed

Cargo.lock

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
use alloc::vec::Vec;
2+
use core::ops::{Mul, MulAssign, Neg};
3+
4+
use openvm_algebra_guest::{
5+
field::{ComplexConjugate, FieldExtension},
6+
DivAssignUnsafe, DivUnsafe, Field,
7+
};
8+
9+
use super::{Bls12_381, Fp, Fp2};
10+
use crate::pairing::{fp12_invert_assign, PairingIntrinsics, SexticExtField};
11+
12+
pub type Fp12 = SexticExtField<Fp2>;
13+
14+
impl Fp12 {
15+
pub fn invert(&self) -> Self {
16+
let mut s = self.clone();
17+
fp12_invert_assign::<Fp, Fp2>(&mut s.c, &Bls12_381::XI);
18+
s
19+
}
20+
}
21+
22+
impl Field for Fp12 {
23+
type SelfRef<'a> = &'a Self;
24+
const ZERO: Self = Self::new([Fp2::ZERO; 6]);
25+
const ONE: Self = Self::new([
26+
Fp2::ONE,
27+
Fp2::ZERO,
28+
Fp2::ZERO,
29+
Fp2::ZERO,
30+
Fp2::ZERO,
31+
Fp2::ZERO,
32+
]);
33+
34+
fn double_assign(&mut self) {
35+
*self += self.clone();
36+
}
37+
38+
fn square_assign(&mut self) {
39+
*self *= self.clone();
40+
}
41+
}
42+
43+
impl FieldExtension<Fp2> for Fp12 {
44+
const D: usize = 6;
45+
type Coeffs = [Fp2; 6];
46+
47+
fn from_coeffs(coeffs: Self::Coeffs) -> Self {
48+
Self::new(coeffs)
49+
}
50+
51+
fn from_bytes(bytes: &[u8]) -> Self {
52+
assert_eq!(bytes.len(), 576);
53+
Self::from_coeffs([
54+
Fp2::from_bytes(&bytes[0..96]),
55+
Fp2::from_bytes(&bytes[96..192]),
56+
Fp2::from_bytes(&bytes[192..288]),
57+
Fp2::from_bytes(&bytes[288..384]),
58+
Fp2::from_bytes(&bytes[384..480]),
59+
Fp2::from_bytes(&bytes[480..576]),
60+
])
61+
}
62+
63+
fn to_coeffs(self) -> Self::Coeffs {
64+
self.c
65+
}
66+
67+
fn to_bytes(&self) -> Vec<u8> {
68+
let mut bytes = Vec::with_capacity(576);
69+
for coeff in self.clone().to_coeffs() {
70+
bytes.extend_from_slice(&coeff.to_bytes());
71+
}
72+
bytes
73+
}
74+
75+
fn embed(c0: Fp2) -> Self {
76+
Self::new([c0, Fp2::ZERO, Fp2::ZERO, Fp2::ZERO, Fp2::ZERO, Fp2::ZERO])
77+
}
78+
79+
/// We assume that the frobenius map power is < 12
80+
fn frobenius_map(&self, power: usize) -> Self {
81+
if power & 1 != 0 {
82+
let c0 = self.c[0].clone().conjugate();
83+
let c1 = self.c[1].clone().conjugate() * &Bls12_381::FROBENIUS_COEFFS[power][0];
84+
let c2 = self.c[2].clone().conjugate() * &Bls12_381::FROBENIUS_COEFFS[power][1];
85+
let c3 = self.c[3].clone().conjugate() * &Bls12_381::FROBENIUS_COEFFS[power][2];
86+
let c4 = self.c[4].clone().conjugate() * &Bls12_381::FROBENIUS_COEFFS[power][3];
87+
let c5 = self.c[5].clone().conjugate() * &Bls12_381::FROBENIUS_COEFFS[power][4];
88+
Self::new([c0, c1, c2, c3, c4, c5])
89+
} else {
90+
let c0 = self.c[0].clone();
91+
let c1 = &self.c[1] * &Bls12_381::FROBENIUS_COEFFS[power][0];
92+
let c2 = &self.c[2] * &Bls12_381::FROBENIUS_COEFFS[power][1];
93+
let c3 = &self.c[3] * &Bls12_381::FROBENIUS_COEFFS[power][2];
94+
let c4 = &self.c[4] * &Bls12_381::FROBENIUS_COEFFS[power][3];
95+
let c5 = &self.c[5] * &Bls12_381::FROBENIUS_COEFFS[power][4];
96+
Self::new([c0, c1, c2, c3, c4, c5])
97+
}
98+
}
99+
100+
fn mul_base(&self, rhs: &Fp2) -> Self {
101+
Self::new([
102+
&self.c[0] * rhs,
103+
&self.c[1] * rhs,
104+
&self.c[2] * rhs,
105+
&self.c[3] * rhs,
106+
&self.c[4] * rhs,
107+
&self.c[5] * rhs,
108+
])
109+
}
110+
}
111+
112+
// This is ambiguous. It is conjugation for Fp12 over Fp6.
113+
impl ComplexConjugate for Fp12 {
114+
fn conjugate(self) -> Self {
115+
let [c0, c1, c2, c3, c4, c5] = self.c;
116+
Self::new([c0, -c1, c2, -c3, c4, -c5])
117+
}
118+
119+
fn conjugate_assign(&mut self) {
120+
self.c[1].neg_assign();
121+
self.c[3].neg_assign();
122+
self.c[5].neg_assign();
123+
}
124+
}
125+
126+
impl<'a> MulAssign<&'a Fp12> for Fp12 {
127+
#[inline(always)]
128+
fn mul_assign(&mut self, other: &'a Fp12) {
129+
*self = crate::pairing::sextic_tower_mul(self, other, &Bls12_381::XI);
130+
}
131+
}
132+
133+
impl<'a> Mul<&'a Fp12> for &'a Fp12 {
134+
type Output = Fp12;
135+
#[inline(always)]
136+
fn mul(self, other: &'a Fp12) -> Self::Output {
137+
crate::pairing::sextic_tower_mul(self, other, &Bls12_381::XI)
138+
}
139+
}
140+
141+
impl MulAssign for Fp12 {
142+
#[inline(always)]
143+
fn mul_assign(&mut self, other: Self) {
144+
self.mul_assign(&other);
145+
}
146+
}
147+
148+
impl Mul for Fp12 {
149+
type Output = Self;
150+
#[inline(always)]
151+
fn mul(mut self, other: Self) -> Self::Output {
152+
self *= other;
153+
self
154+
}
155+
}
156+
157+
impl<'a> Mul<&'a Fp12> for Fp12 {
158+
type Output = Self;
159+
#[inline(always)]
160+
fn mul(mut self, other: &'a Fp12) -> Self::Output {
161+
self *= other;
162+
self
163+
}
164+
}
165+
166+
impl<'a> DivAssignUnsafe<&'a Fp12> for Fp12 {
167+
#[inline(always)]
168+
fn div_assign_unsafe(&mut self, other: &'a Fp12) {
169+
*self *= other.invert();
170+
}
171+
}
172+
173+
impl<'a> DivUnsafe<&'a Fp12> for &'a Fp12 {
174+
type Output = Fp12;
175+
#[inline(always)]
176+
fn div_unsafe(self, other: &'a Fp12) -> Self::Output {
177+
let mut res = self.clone();
178+
res.div_assign_unsafe(other);
179+
res
180+
}
181+
}
182+
183+
impl DivAssignUnsafe for Fp12 {
184+
#[inline(always)]
185+
fn div_assign_unsafe(&mut self, other: Self) {
186+
*self *= other.invert();
187+
}
188+
}
189+
190+
impl DivUnsafe for Fp12 {
191+
type Output = Self;
192+
#[inline(always)]
193+
fn div_unsafe(mut self, other: Self) -> Self::Output {
194+
self.div_assign_unsafe(other);
195+
self
196+
}
197+
}
198+
199+
impl<'a> DivUnsafe<&'a Fp12> for Fp12 {
200+
type Output = Self;
201+
#[inline(always)]
202+
fn div_unsafe(mut self, other: &'a Fp12) -> Self::Output {
203+
self.div_assign_unsafe(other);
204+
self
205+
}
206+
}
207+
208+
impl Neg for Fp12 {
209+
type Output = Fp12;
210+
#[inline(always)]
211+
fn neg(self) -> Self::Output {
212+
Self::ZERO - &self
213+
}
214+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use alloc::vec::Vec;
2+
use core::ops::Neg;
3+
4+
use openvm_algebra_complex_macros::{complex_declare, complex_impl_field};
5+
use openvm_algebra_guest::{field::FieldExtension, Field, IntMod};
6+
7+
use super::Fp;
8+
9+
#[cfg(not(target_os = "zkvm"))]
10+
// Used in Fp2Extension config
11+
pub const BLS12_381_COMPLEX_STRUCT_NAME: &str = "Bls12_381Fp2";
12+
13+
// The struct name needs to be globally unique for linking purposes.
14+
// The mod_type is a path used only in the struct definition.
15+
complex_declare! {
16+
Bls12_381Fp2 { mod_type = Fp }
17+
}
18+
19+
complex_impl_field! {
20+
Bls12_381Fp2,
21+
}
22+
23+
pub type Fp2 = Bls12_381Fp2;
24+
25+
impl FieldExtension<Fp> for Fp2 {
26+
const D: usize = 2;
27+
type Coeffs = [Fp; 2];
28+
29+
fn from_coeffs([c0, c1]: Self::Coeffs) -> Self {
30+
Self { c0, c1 }
31+
}
32+
33+
fn from_bytes(bytes: &[u8]) -> Self {
34+
assert_eq!(bytes.len(), 96);
35+
Self::from_coeffs([
36+
Fp::from_const_bytes(bytes[0..48].try_into().unwrap()),
37+
Fp::from_const_bytes(bytes[48..96].try_into().unwrap()),
38+
])
39+
}
40+
41+
fn to_coeffs(self) -> Self::Coeffs {
42+
[self.c0, self.c1]
43+
}
44+
45+
fn to_bytes(&self) -> Vec<u8> {
46+
let mut bytes = Vec::with_capacity(96);
47+
bytes.extend_from_slice(self.c0.as_le_bytes());
48+
bytes.extend_from_slice(self.c1.as_le_bytes());
49+
bytes
50+
}
51+
52+
fn embed(base_elem: Fp) -> Self {
53+
Self {
54+
c0: base_elem,
55+
c1: <Fp as Field>::ZERO,
56+
}
57+
}
58+
59+
fn frobenius_map(&self, power: usize) -> Self {
60+
if power % 2 == 0 {
61+
self.clone()
62+
} else {
63+
Self {
64+
c0: self.c0.clone(),
65+
c1: (&self.c1).neg(),
66+
}
67+
}
68+
}
69+
70+
fn mul_base(&self, rhs: &Fp) -> Self {
71+
Self {
72+
c0: &self.c0 * rhs,
73+
c1: &self.c1 * rhs,
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)