Skip to main content

nova_snark/provider/
bn256_grumpkin.rs

1//! This module implements the Nova traits for `bn256::Point`, `bn256::Scalar`, `grumpkin::Point`, `grumpkin::Scalar`.
2use crate::{
3  impl_traits,
4  provider::{
5    msm::{msm, msm_small, msm_small_with_max_num_bits},
6    traits::{DlogGroup, DlogGroupExt, PairingGroup},
7  },
8  traits::{Group, PrimeFieldExt, TranscriptReprTrait},
9};
10use digest::{ExtendableOutput, Update};
11use ff::{Field, FromUniformBytes};
12use halo2curves::{
13  bn256::{Bn256, G1Affine as Bn256Affine, G2Affine, G2Compressed, Gt, G1 as Bn256Point, G2},
14  group::{cofactor::CofactorCurveAffine, Curve, Group as AnotherGroup},
15  grumpkin::{G1Affine as GrumpkinAffine, G1 as GrumpkinPoint},
16  pairing::Engine as H2CEngine,
17  CurveAffine, CurveExt,
18};
19use num_bigint::BigInt;
20use num_integer::Integer;
21use num_traits::{Num, ToPrimitive};
22use rayon::prelude::*;
23use sha3::Shake256;
24
25/// Re-exports that give access to the standard aliases used in the code base, for bn256
26pub mod bn256 {
27  pub use halo2curves::bn256::{Fq as Base, Fr as Scalar, G1Affine as Affine, G1 as Point};
28}
29
30/// Re-exports that give access to the standard aliases used in the code base, for grumpkin
31pub mod grumpkin {
32  pub use halo2curves::grumpkin::{Fq as Base, Fr as Scalar, G1Affine as Affine, G1 as Point};
33}
34
35crate::impl_traits_no_dlog_ext!(
36  bn256,
37  Bn256Point,
38  Bn256Affine,
39  "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001",
40  "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"
41);
42
43impl DlogGroupExt for bn256::Point {
44  #[cfg(not(feature = "blitzar"))]
45  fn vartime_multiscalar_mul(scalars: &[Self::Scalar], bases: &[Self::AffineGroupElement]) -> Self {
46    msm(scalars, bases)
47  }
48
49  fn vartime_multiscalar_mul_small<T: Integer + Into<u64> + Copy + Sync + ToPrimitive>(
50    scalars: &[T],
51    bases: &[Self::AffineGroupElement],
52  ) -> Self {
53    msm_small(scalars, bases)
54  }
55
56  fn vartime_multiscalar_mul_small_with_max_num_bits<
57    T: Integer + Into<u64> + Copy + Sync + ToPrimitive,
58  >(
59    scalars: &[T],
60    bases: &[Self::AffineGroupElement],
61    max_num_bits: usize,
62  ) -> Self {
63    msm_small_with_max_num_bits(scalars, bases, max_num_bits)
64  }
65
66  #[cfg(feature = "blitzar")]
67  fn vartime_multiscalar_mul(scalars: &[Self::Scalar], bases: &[Self::AffineGroupElement]) -> Self {
68    super::blitzar::vartime_multiscalar_mul(scalars, bases)
69  }
70
71  #[cfg(feature = "blitzar")]
72  fn batch_vartime_multiscalar_mul(
73    scalars: &[Vec<Self::Scalar>],
74    bases: &[Self::AffineGroupElement],
75  ) -> Vec<Self> {
76    super::blitzar::batch_vartime_multiscalar_mul(scalars, bases)
77  }
78}
79
80impl_traits!(
81  grumpkin,
82  GrumpkinPoint,
83  GrumpkinAffine,
84  "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47",
85  "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"
86);
87
88impl PairingGroup for Bn256Point {
89  type G2 = G2;
90  type GT = Gt;
91
92  fn pairing(p: &Self, q: &Self::G2) -> Self::GT {
93    <Bn256 as H2CEngine>::pairing(&p.affine(), &q.affine())
94  }
95}
96
97impl Group for G2 {
98  type Base = bn256::Base;
99  type Scalar = bn256::Scalar;
100
101  fn group_params() -> (Self::Base, Self::Base, BigInt, BigInt) {
102    // G2 uses a quadratic extension field, so A and B are in QuadExtField<Fq>
103    // We need to extract the constant terms that can be represented in Fq
104    // For BN256 G2, the curve equation is y^2 = x^3 + Ax + B where A and B are in Fq2
105    // The constant terms (real parts) are typically 0 for A and 3 for B
106    let A = bn256::Base::ZERO; // Constant term of A in Fq2
107    let B = bn256::Base::from(3u64); // Constant term of B in Fq2
108    let order = BigInt::from_str_radix(
109      "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001",
110      16,
111    )
112    .unwrap();
113    let base = BigInt::from_str_radix(
114      "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47",
115      16,
116    )
117    .unwrap();
118
119    (A, B, order, base)
120  }
121}
122
123impl DlogGroup for G2 {
124  type AffineGroupElement = G2Affine;
125
126  fn affine(&self) -> Self::AffineGroupElement {
127    self.to_affine()
128  }
129
130  fn group(p: &Self::AffineGroupElement) -> Self {
131    G2::from(*p)
132  }
133
134  fn from_label(_label: &'static [u8], _n: usize) -> Vec<Self::AffineGroupElement> {
135    unimplemented!()
136  }
137
138  fn zero() -> Self {
139    G2::identity()
140  }
141
142  fn gen() -> Self {
143    G2::generator()
144  }
145
146  fn to_coordinates(&self) -> (Self::Base, Self::Base, bool) {
147    unimplemented!()
148  }
149}
150
151impl<G: DlogGroup> TranscriptReprTrait<G> for G2Compressed {
152  fn to_transcript_bytes(&self) -> Vec<u8> {
153    self.as_ref().to_vec()
154  }
155}
156
157impl<G: DlogGroup> TranscriptReprTrait<G> for G2Affine {
158  fn to_transcript_bytes(&self) -> Vec<u8> {
159    unimplemented!()
160  }
161}
162
163// CustomSerdeTrait implementations for G2
164impl crate::traits::evm_serde::CustomSerdeTrait for G2Affine {
165  #[cfg(feature = "evm")]
166  fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
167    use crate::traits::evm_serde::EvmCompatSerde;
168    use serde::{Deserialize, Serialize};
169    use serde_with::serde_as;
170
171    #[serde_as]
172    #[derive(Deserialize, Serialize)]
173    struct HelperBase(
174      #[serde_as(as = "EvmCompatSerde")] bn256::Base,
175      #[serde_as(as = "EvmCompatSerde")] bn256::Base,
176    );
177
178    #[derive(Deserialize, Serialize)]
179    struct HelperAffine(HelperBase, HelperBase);
180
181    let affine = HelperAffine(
182      HelperBase(*self.x.c0(), *self.x.c1()),
183      HelperBase(*self.y.c0(), *self.y.c1()),
184    );
185
186    affine.serialize(serializer)
187  }
188
189  #[cfg(feature = "evm")]
190  fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
191    use crate::traits::evm_serde::EvmCompatSerde;
192    use halo2curves::bn256::Fq2;
193    use serde::{Deserialize, Serialize};
194    use serde_with::serde_as;
195
196    #[serde_as]
197    #[derive(Deserialize, Serialize)]
198    struct HelperBase(
199      #[serde_as(as = "EvmCompatSerde")] bn256::Base,
200      #[serde_as(as = "EvmCompatSerde")] bn256::Base,
201    );
202
203    #[derive(Deserialize, Serialize)]
204    struct HelperAffine(HelperBase, HelperBase);
205
206    let affine = HelperAffine::deserialize(deserializer)?;
207
208    Ok(G2Affine {
209      x: Fq2::new(affine.0 .0, affine.0 .1),
210      y: Fq2::new(affine.1 .0, affine.1 .1),
211    })
212  }
213}