3
3
//! Helpers for converting Arkworks types to BigUint-tuples as expected by the
4
4
//! Solidity Groth16 Verifier smart contracts
5
5
use ark_bls12_381:: {
6
- Bls12_381 , Fq as bls12_381_fq, Fq2 as bls12_381_Fq2, G1Affine as bls12_381_G1Affine ,
7
- G2Affine as bls12_381_G2Affine,
6
+ Bls12_381 , Fq as bls12_381_fq, Fq2 as bls12_381_Fq2, Fr as bls12_381_Fr ,
7
+ G1Affine as bls12_381_G1Affine , G2Affine as bls12_381_G2Affine,
8
8
} ;
9
9
use ark_ec:: AffineRepr ;
10
10
use ark_ff:: { BigInteger , PrimeField } ;
11
11
use num:: BigUint ;
12
12
use num_traits:: Zero ;
13
13
14
14
use ark_bn254:: {
15
- Bn254 , Fq as bn254_Fq, Fq2 as bn254_Fq2, Fr , G1Affine as bn254_G1Affine,
15
+ Bn254 , Fq as bn254_Fq, Fq2 as bn254_Fq2, Fr as bn254_Fr , G1Affine as bn254_G1Affine,
16
16
G2Affine as bn254_G2Affine,
17
17
} ;
18
18
use ark_serialize:: CanonicalDeserialize ;
19
19
20
- const BN254_BUF_SIZE : usize = 32 ;
21
- const BLS12_381_BUF_SIZE : usize = 48 ;
22
-
23
20
pub const PROTOCOL_GROTH16 : & str = "groth16" ;
24
21
pub const CURVE_BN254 : & str = "bn128" ;
25
22
pub const CURVE_BLS12_381 : & str = "bls12381" ;
26
23
27
24
pub struct Inputs ( pub Vec < BigUint > ) ;
28
25
29
- impl From < & [ Fr ] > for Inputs {
30
- fn from ( src : & [ Fr ] ) -> Self {
26
+ impl From < & [ bn254_Fr ] > for Inputs {
27
+ fn from ( src : & [ bn254_Fr ] ) -> Self {
31
28
let els = src. iter ( ) . map ( |point| point_to_biguint ( * point) ) . collect ( ) ;
29
+ Self ( els)
30
+ }
31
+ }
32
32
33
+ impl From < & [ bls12_381_Fr ] > for Inputs {
34
+ fn from ( src : & [ bls12_381_Fr ] ) -> Self {
35
+ let els = src. iter ( ) . map ( |point| point_to_biguint ( * point) ) . collect ( ) ;
33
36
Self ( els)
34
37
}
35
38
}
36
39
40
+ impl From < Inputs > for Vec < bn254_Fr > {
41
+ fn from ( inputs : Inputs ) -> Self {
42
+ inputs
43
+ . 0
44
+ . iter ( )
45
+ . map ( |biguint| biguint_to_point ( biguint. clone ( ) ) )
46
+ . collect ( )
47
+ }
48
+ }
49
+
50
+ impl From < Inputs > for Vec < bls12_381_Fr > {
51
+ fn from ( inputs : Inputs ) -> Self {
52
+ inputs
53
+ . 0
54
+ . iter ( )
55
+ . map ( |biguint| biguint_to_point ( biguint. clone ( ) ) )
56
+ . collect ( )
57
+ }
58
+ }
59
+
37
60
// Follow the interface: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/snarkjs/index.d.cts
38
61
#[ derive( Default , Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
39
62
pub struct G1 {
@@ -51,8 +74,8 @@ impl G1 {
51
74
52
75
// BN254
53
76
pub fn to_bn254 ( self ) -> bn254_G1Affine {
54
- let x: bn254_Fq = biguint_to_point ( self . x , BN254_BUF_SIZE ) ;
55
- let y: bn254_Fq = biguint_to_point ( self . y , BN254_BUF_SIZE ) ;
77
+ let x: bn254_Fq = biguint_to_point ( self . x ) ;
78
+ let y: bn254_Fq = biguint_to_point ( self . y ) ;
56
79
if x. is_zero ( ) && y. is_zero ( ) {
57
80
bn254_G1Affine:: identity ( )
58
81
} else {
@@ -71,8 +94,8 @@ impl G1 {
71
94
72
95
// BLS12-381
73
96
pub fn to_bls12_381 ( self ) -> bls12_381_G1Affine {
74
- let x: bls12_381_fq = biguint_to_point ( self . x , BLS12_381_BUF_SIZE ) ;
75
- let y: bls12_381_fq = biguint_to_point ( self . y , BLS12_381_BUF_SIZE ) ;
97
+ let x: bls12_381_fq = biguint_to_point ( self . x ) ;
98
+ let y: bls12_381_fq = biguint_to_point ( self . y ) ;
76
99
if x. is_zero ( ) && y. is_zero ( ) {
77
100
bls12_381_G1Affine:: identity ( )
78
101
} else {
@@ -111,12 +134,12 @@ impl G2 {
111
134
112
135
// BN254
113
136
pub fn to_bn254 ( self ) -> bn254_G2Affine {
114
- let c0 = biguint_to_point ( self . x [ 0 ] . clone ( ) , BN254_BUF_SIZE ) ;
115
- let c1 = biguint_to_point ( self . x [ 1 ] . clone ( ) , BN254_BUF_SIZE ) ;
137
+ let c0 = biguint_to_point ( self . x [ 0 ] . clone ( ) ) ;
138
+ let c1 = biguint_to_point ( self . x [ 1 ] . clone ( ) ) ;
116
139
let x = bn254_Fq2:: new ( c0, c1) ;
117
140
118
- let c0 = biguint_to_point ( self . y [ 0 ] . clone ( ) , BN254_BUF_SIZE ) ;
119
- let c1 = biguint_to_point ( self . y [ 1 ] . clone ( ) , BN254_BUF_SIZE ) ;
141
+ let c0 = biguint_to_point ( self . y [ 0 ] . clone ( ) ) ;
142
+ let c1 = biguint_to_point ( self . y [ 1 ] . clone ( ) ) ;
120
143
let y = bn254_Fq2:: new ( c0, c1) ;
121
144
122
145
if x. is_zero ( ) && y. is_zero ( ) {
@@ -137,12 +160,12 @@ impl G2 {
137
160
138
161
// BLS12-381
139
162
pub fn to_bls12_381 ( self ) -> bls12_381_G2Affine {
140
- let c0 = biguint_to_point ( self . x [ 0 ] . clone ( ) , BLS12_381_BUF_SIZE ) ;
141
- let c1 = biguint_to_point ( self . x [ 1 ] . clone ( ) , BLS12_381_BUF_SIZE ) ;
163
+ let c0 = biguint_to_point ( self . x [ 0 ] . clone ( ) ) ;
164
+ let c1 = biguint_to_point ( self . x [ 1 ] . clone ( ) ) ;
142
165
let x = bls12_381_Fq2:: new ( c0, c1) ;
143
166
144
- let c0 = biguint_to_point ( self . y [ 0 ] . clone ( ) , BLS12_381_BUF_SIZE ) ;
145
- let c1 = biguint_to_point ( self . y [ 1 ] . clone ( ) , BLS12_381_BUF_SIZE ) ;
167
+ let c0 = biguint_to_point ( self . y [ 0 ] . clone ( ) ) ;
168
+ let c1 = biguint_to_point ( self . y [ 1 ] . clone ( ) ) ;
146
169
let y = bls12_381_Fq2:: new ( c0, c1) ;
147
170
148
171
if x. is_zero ( ) && y. is_zero ( ) {
@@ -222,7 +245,8 @@ impl From<Proof> for ark_groth16::Proof<Bls12_381> {
222
245
}
223
246
224
247
// Helper for converting a PrimeField to its BigUint representation for Ethereum compatibility
225
- fn biguint_to_point < F : PrimeField > ( point : BigUint , buf_size : usize ) -> F {
248
+ fn biguint_to_point < F : PrimeField > ( point : BigUint ) -> F {
249
+ let buf_size: usize = ( ( F :: MODULUS_BIT_SIZE + 7 ) / 8 ) . try_into ( ) . unwrap ( ) ; // Rounds up the division
226
250
let mut buf = point. to_bytes_le ( ) ;
227
251
buf. resize ( buf_size, 0u8 ) ;
228
252
let bigint = F :: BigInt :: deserialize_uncompressed ( & buf[ ..] ) . expect ( "always works" ) ;
@@ -239,9 +263,8 @@ fn point_to_biguint<F: PrimeField>(point: F) -> BigUint {
239
263
240
264
#[ cfg( test) ]
241
265
mod tests {
242
- use crate :: prover:: ethereum:: {
243
- biguint_to_point, point_to_biguint, Proof , BLS12_381_BUF_SIZE , BN254_BUF_SIZE , G1 , G2 ,
244
- } ;
266
+ use crate :: prover:: ethereum:: { biguint_to_point, point_to_biguint, Inputs , Proof , G1 , G2 } ;
267
+ use num:: BigUint ;
245
268
246
269
mod bn254 {
247
270
use super :: * ;
@@ -270,7 +293,7 @@ mod tests {
270
293
fn convert_fq ( ) {
271
294
let el = fq ( ) ;
272
295
let el2 = point_to_biguint ( el) ;
273
- let el3: Fq = biguint_to_point ( el2. clone ( ) , BN254_BUF_SIZE ) ;
296
+ let el3: Fq = biguint_to_point ( el2. clone ( ) ) ;
274
297
let el4 = point_to_biguint ( el3) ;
275
298
assert_eq ! ( el, el3) ;
276
299
assert_eq ! ( el2, el4) ;
@@ -280,7 +303,7 @@ mod tests {
280
303
fn convert_fr ( ) {
281
304
let el = fr ( ) ;
282
305
let el2 = point_to_biguint ( el) ;
283
- let el3: Fr = biguint_to_point ( el2. clone ( ) , BN254_BUF_SIZE ) ;
306
+ let el3: Fr = biguint_to_point ( el2. clone ( ) ) ;
284
307
let el4 = point_to_biguint ( el3) ;
285
308
assert_eq ! ( el, el3) ;
286
309
assert_eq ! ( el2, el4) ;
@@ -317,6 +340,40 @@ mod tests {
317
340
let p3 = ark_groth16:: Proof :: from ( p2) ;
318
341
assert_eq ! ( p, p3) ;
319
342
}
343
+
344
+ #[ test]
345
+ fn convert_fr_inputs_to_biguint ( ) {
346
+ let bn254_1 = Fr :: from ( 1u32 ) ;
347
+ let bn254_2 = Fr :: from ( 2u32 ) ;
348
+ let bn254_3 = Fr :: from ( 3u32 ) ;
349
+
350
+ let bn254_slice: & [ Fr ] = & [ bn254_1, bn254_2, bn254_3] ;
351
+
352
+ let result: Inputs = bn254_slice. into ( ) ;
353
+
354
+ assert_eq ! ( result. 0 . len( ) , 3 ) ;
355
+
356
+ assert_eq ! ( result. 0 [ 0 ] , BigUint :: from( 1u32 ) ) ;
357
+ assert_eq ! ( result. 0 [ 1 ] , BigUint :: from( 2u32 ) ) ;
358
+ assert_eq ! ( result. 0 [ 2 ] , BigUint :: from( 3u32 ) ) ;
359
+ }
360
+
361
+ #[ test]
362
+ fn convert_biguint_to_fr_inputs ( ) {
363
+ let biguint1 = BigUint :: from ( 1u32 ) ;
364
+ let biguint2 = BigUint :: from ( 2u32 ) ;
365
+ let biguint3 = BigUint :: from ( 3u32 ) ;
366
+
367
+ let inputs = Inputs ( vec ! [ biguint1, biguint2, biguint3] ) ;
368
+
369
+ let result: Vec < Fr > = inputs. into ( ) ;
370
+
371
+ assert_eq ! ( result. len( ) , 3 ) ;
372
+
373
+ assert_eq ! ( result[ 0 ] , Fr :: from( BigUint :: from( 1u32 ) ) ) ;
374
+ assert_eq ! ( result[ 1 ] , Fr :: from( BigUint :: from( 2u32 ) ) ) ;
375
+ assert_eq ! ( result[ 2 ] , Fr :: from( BigUint :: from( 3u32 ) ) ) ;
376
+ }
320
377
}
321
378
322
379
mod bls12_381 {
@@ -346,7 +403,7 @@ mod tests {
346
403
fn convert_fq ( ) {
347
404
let el = fq ( ) ;
348
405
let el2 = point_to_biguint ( el) ;
349
- let el3: Fq = biguint_to_point ( el2. clone ( ) , BLS12_381_BUF_SIZE ) ;
406
+ let el3: Fq = biguint_to_point ( el2. clone ( ) ) ;
350
407
let el4 = point_to_biguint ( el3) ;
351
408
assert_eq ! ( el, el3) ;
352
409
assert_eq ! ( el2, el4) ;
@@ -356,7 +413,7 @@ mod tests {
356
413
fn convert_fr ( ) {
357
414
let el = fr ( ) ;
358
415
let el2 = point_to_biguint ( el) ;
359
- let el3: Fr = biguint_to_point ( el2. clone ( ) , BLS12_381_BUF_SIZE ) ;
416
+ let el3: Fr = biguint_to_point ( el2. clone ( ) ) ;
360
417
let el4 = point_to_biguint ( el3) ;
361
418
assert_eq ! ( el, el3) ;
362
419
assert_eq ! ( el2, el4) ;
@@ -393,5 +450,39 @@ mod tests {
393
450
let p3 = ark_groth16:: Proof :: from ( p2) ;
394
451
assert_eq ! ( p, p3) ;
395
452
}
453
+
454
+ #[ test]
455
+ fn convert_fr_inputs_to_biguint ( ) {
456
+ let bn254_1 = Fr :: from ( 1u32 ) ;
457
+ let bn254_2 = Fr :: from ( 2u32 ) ;
458
+ let bn254_3 = Fr :: from ( 3u32 ) ;
459
+
460
+ let bn254_slice: & [ Fr ] = & [ bn254_1, bn254_2, bn254_3] ;
461
+
462
+ let result: Inputs = bn254_slice. into ( ) ;
463
+
464
+ assert_eq ! ( result. 0 . len( ) , 3 ) ;
465
+
466
+ assert_eq ! ( result. 0 [ 0 ] , BigUint :: from( 1u32 ) ) ;
467
+ assert_eq ! ( result. 0 [ 1 ] , BigUint :: from( 2u32 ) ) ;
468
+ assert_eq ! ( result. 0 [ 2 ] , BigUint :: from( 3u32 ) ) ;
469
+ }
470
+
471
+ #[ test]
472
+ fn convert_biguint_to_fr_inputs ( ) {
473
+ let biguint1 = BigUint :: from ( 1u32 ) ;
474
+ let biguint2 = BigUint :: from ( 2u32 ) ;
475
+ let biguint3 = BigUint :: from ( 3u32 ) ;
476
+
477
+ let inputs = Inputs ( vec ! [ biguint1, biguint2, biguint3] ) ;
478
+
479
+ let result: Vec < Fr > = inputs. into ( ) ;
480
+
481
+ assert_eq ! ( result. len( ) , 3 ) ;
482
+
483
+ assert_eq ! ( result[ 0 ] , Fr :: from( BigUint :: from( 1u32 ) ) ) ;
484
+ assert_eq ! ( result[ 1 ] , Fr :: from( BigUint :: from( 2u32 ) ) ) ;
485
+ assert_eq ! ( result[ 2 ] , Fr :: from( BigUint :: from( 3u32 ) ) ) ;
486
+ }
396
487
}
397
488
}
0 commit comments