11package org .hyperledger .besu .nativelib .blst ;
22
3- import com .google .common .base .Stopwatch ;
43import supranational .blst .P1 ;
54import supranational .blst .P1_Affine ;
65import supranational .blst .P2 ;
109
1110import java .util .Optional ;
1211
12+ /**
13+ * This class implements BLS12-381 using JBLST and BLST, and therefore does not strictly need to be
14+ * in besu-native.
15+ *
16+ * TODO: map_to_g1 and map_to_g2 are not currently available in blst bindings, and are
17+ * commented out for now.
18+ */
1319public class Bls12381 {
1420
1521 static final byte [] PAIRING_FALSE = new byte [32 ];
1622 static final byte [] PAIRING_TRUE = new byte [32 ];
23+
1724 static {
1825 PAIRING_TRUE [31 ] = 0x01 ;
1926 }
2027
28+
2129 record G1MulInput (byte [] g1 , Scalar s ) {
2230 static G1MulInput unpad (byte [] packedG1Mul ) {
2331 if (packedG1Mul .length != 160 ) {
@@ -41,7 +49,7 @@ static G1MulInput[] unpadMany(byte[] packedG1MultiExpr) {
4149 int length = packedG1MultiExpr .length / 160 ;
4250 G1MulInput [] mulInputs = new G1MulInput [length ];
4351
44- for (int i =0 ; i < length ; i ++) {
52+ for (int i = 0 ; i < length ; i ++) {
4553 byte [] g1 = new byte [96 ];
4654 System .arraycopy (packedG1MultiExpr , i * 160 + 16 , g1 , 0 , 48 );
4755 System .arraycopy (packedG1MultiExpr , i * 160 + 80 , g1 , 48 , 48 );
@@ -55,6 +63,7 @@ static G1MulInput[] unpadMany(byte[] packedG1MultiExpr) {
5563
5664 }
5765
66+
5867 record G1AddInput (byte [] g1a , byte [] g1b ) {
5968 static G1AddInput unpadPair (byte [] packedG1Affine ) {
6069 if (packedG1Affine .length != 256 ) {
@@ -71,6 +80,7 @@ static G1AddInput unpadPair(byte[] packedG1Affine) {
7180 }
7281 }
7382
83+
7484 public record G1Output (byte [] padded ) {
7585 static G1Output pad (byte [] unpadded ) {
7686 if (unpadded .length != 96 ) {
@@ -83,10 +93,12 @@ static G1Output pad(byte[] unpadded) {
8393 }
8494 }
8595
96+
8697 public record G1Result (G1Output g1Out , Optional <String > optError ) {
8798 }
8899
89- record G2MulInput (byte [] g2 , Scalar s ){
100+
101+ record G2MulInput (byte [] g2 , Scalar s ) {
90102 static G2MulInput unpadPair (byte [] packedG2Mul ) {
91103 if (packedG2Mul .length != 288 ) {
92104 throw new RuntimeException (
@@ -103,15 +115,15 @@ static G2MulInput unpadPair(byte[] packedG2Mul) {
103115 return new G2MulInput (g2 , s );
104116 }
105117
106- static G2MulInput [] unpadMany (byte [] packedG2MultiExpr ){
118+ static G2MulInput [] unpadMany (byte [] packedG2MultiExpr ) {
107119 if (packedG2MultiExpr .length % 288 != 0 || packedG2MultiExpr .length == 0 ) {
108120 throw new RuntimeException (
109121 "BLST_ERROR: invalid input parameters, invalid input length for G2 MultiExpr" );
110122 }
111123 int length = packedG2MultiExpr .length / 288 ;
112124 G2MulInput [] mulInputs = new G2MulInput [length ];
113125
114- for (int i =0 ; i < length ; i ++) {
126+ for (int i = 0 ; i < length ; i ++) {
115127 byte [] g2 = new byte [192 ];
116128 System .arraycopy (packedG2MultiExpr , i * 288 + 16 , g2 , 48 , 48 );
117129 System .arraycopy (packedG2MultiExpr , i * 288 + 80 , g2 , 0 , 48 );
@@ -127,6 +139,7 @@ static G2MulInput[] unpadMany(byte[] packedG2MultiExpr){
127139
128140 }
129141
142+
130143 record G2AddInput (byte [] g2a , byte [] g2b ) {
131144 static G2AddInput unpadPair (byte [] packedG2Affine ) {
132145 if (packedG2Affine .length != 512 ) {
@@ -147,6 +160,7 @@ static G2AddInput unpadPair(byte[] packedG2Affine) {
147160 }
148161 }
149162
163+
150164 public record G2Output (byte [] padded ) {
151165 static G2Output pad (byte [] unpadded ) {
152166 if (unpadded .length != 192 ) {
@@ -161,23 +175,25 @@ static G2Output pad(byte[] unpadded) {
161175 }
162176 }
163177
178+
164179 public record G2Result (G2Output g2Out , Optional <String > optError ) {
165180 }
166181
167- public record PairingInput (byte [] g1 , byte [] g2 ) {
168- static PairingInput [] parseMany (byte [] packedPairingInput ) {
182+
183+ public record PairingInput (byte [] g1 , byte [] g2 ) {
184+ static PairingInput [] parseMany (byte [] packedPairingInput ) {
169185 if (packedPairingInput .length % 384 != 0 || packedPairingInput .length == 0 ) {
170186 throw new RuntimeException (
171187 "BLST_ERROR: invalid input parameters, invalid input length for pairing" );
172188 }
173189 final int len = packedPairingInput .length / 384 ;
174190 final PairingInput [] res = new PairingInput [len ];
175- for (int i = 0 ; i < len ; i ++) {
176- byte [] g1 = new byte [96 ];
191+ for (int i = 0 ; i < len ; i ++) {
192+ byte [] g1 = new byte [96 ];
177193 System .arraycopy (packedPairingInput , i * 384 + 16 , g1 , 0 , 48 );
178194 System .arraycopy (packedPairingInput , i * 384 + 80 , g1 , 48 , 48 );
179195
180- byte [] g2 = new byte [192 ];
196+ byte [] g2 = new byte [192 ];
181197 System .arraycopy (packedPairingInput , i * 384 + 128 + 16 , g2 , 48 , 48 );
182198 System .arraycopy (packedPairingInput , i * 384 + 128 + 80 , g2 , 0 , 48 );
183199 System .arraycopy (packedPairingInput , i * 384 + 128 + 144 , g2 , 144 , 48 );
@@ -188,7 +204,10 @@ static PairingInput[] parseMany(byte [] packedPairingInput) {
188204 }
189205 }
190206
191- public record PairingResult (byte [] result , Optional <String > optError ){}
207+
208+ public record PairingResult (byte [] result , Optional <String > optError ) {
209+ }
210+
192211
193212 public static final Boolean ENABLED = init ();
194213
@@ -234,7 +253,7 @@ public static G1Result g1Add(byte[] packedG1Affines) {
234253 * Multiply G1 affine by scalar, return the result. Perform subgroup checks, per EIP-2537.
235254 *
236255 * @param packedG1Mul 160 byte array, comprising a G1 affine and 32 bit scalar. Points are 48
237- * bytes, with each left padded with 16 bytes, totaling 64 bytes per point.
256+ * bytes, with each left padded with 16 bytes, totaling 64 bytes per point.
238257 * @return g1Result
239258 */
240259 public static G1Result g1Mul (byte [] packedG1Mul ) {
@@ -246,8 +265,7 @@ public static G1Result g1Mul(byte[] packedG1Mul) {
246265 var g1MulInput = G1MulInput .unpad (packedG1Mul );
247266 p1 = new P1 (g1MulInput .g1 );
248267 if (!p1 .in_group ()) {
249- return new G1Result (null ,
250- Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
268+ return new G1Result (null , Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
251269 }
252270 s = g1MulInput .s ;
253271 } catch (Exception ex ) {
@@ -263,11 +281,11 @@ public static G1Result g1Mul(byte[] packedG1Mul) {
263281 }
264282
265283 /**
266- * Multiply G1 affine/scalar pairs, sum, return the result. Perform subgroup checks, per EIP-2537.
284+ * Multiply G1 affine/scalar pairs, sum, return the result. Perform subgroup checks, per
285+ * EIP-2537.
267286 *
268- * @param packedG1MultiExpr byte array, comprising n G1 affine/scalar paris.
269- * Points are 48 bytes, with each left padded with 16 bytes,
270- * totaling 64 bytes per point.
287+ * @param packedG1MultiExpr byte array, comprising n G1 affine/scalar paris. Points are 48 bytes,
288+ * with each left padded with 16 bytes, totaling 64 bytes per point.
271289 * @return g1Result
272290 */
273291 public static G1Result g1MultiExp (byte [] packedG1MultiExpr ) {
@@ -281,8 +299,7 @@ public static G1Result g1MultiExp(byte[] packedG1MultiExpr) {
281299
282300 p1 = new P1 (g1MultiInput [0 ].g1 );
283301 if (!p1 .in_group ()) {
284- return new G1Result (null ,
285- Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
302+ return new G1Result (null , Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
286303 }
287304 s = g1MultiInput [0 ].s ;
288305
@@ -319,7 +336,6 @@ public static G1Result g1MultiExp(byte[] packedG1MultiExpr) {
319336 public static G2Result g2Add (byte [] packedG2Affines ) {
320337 // do not do subgroup checks on G2ADD according to EIP-2537 spec
321338 // get P2 points a and b from affine encoding as jacobian coords
322- Stopwatch sw = Stopwatch .createStarted ();
323339 P2 p2a , p2b ;
324340 try {
325341 var g2AddInput = G2AddInput .unpadPair (packedG2Affines );
@@ -341,7 +357,7 @@ public static G2Result g2Add(byte[] packedG2Affines) {
341357 * Multiply G2 affine by scalar, return the result. Perform subgroup checks, per EIP-2537.
342358 *
343359 * @param packedG2Mul 288 byte array, comprising a G2 affine and 32 bit scalar. Points are 48
344- * bytes, with each left padded with 16 bytes, totaling 64 bytes per point.
360+ * bytes, with each left padded with 16 bytes, totaling 64 bytes per point.
345361 * @return g2Result
346362 */
347363 public static G2Result g2Mul (byte [] packedG2Mul ) {
@@ -353,8 +369,7 @@ public static G2Result g2Mul(byte[] packedG2Mul) {
353369 g2MulInput = G2MulInput .unpadPair (packedG2Mul );
354370 p2 = new P2 (g2MulInput .g2 );
355371 if (!p2 .in_group ()) {
356- return new G2Result (null ,
357- Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
372+ return new G2Result (null , Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
358373 }
359374
360375 } catch (Exception ex ) {
@@ -370,10 +385,12 @@ public static G2Result g2Mul(byte[] packedG2Mul) {
370385 }
371386
372387 /**
373- * Multiply G2 affine/scalar pairs, sum, return the result. Perform subgroup checks, per EIP-2537.
388+ * Multiply G2 affine/scalar pairs, sum, return the result. Perform subgroup checks, per
389+ * EIP-2537.
374390 *
375391 * @param packedG2MultiExpr byte array, comprising a G2 affine and scalar paris. Points are 48
376- * bytes, with each left padded with 16 bytes, totaling 64 bytes per point.
392+ * bytes, with each left padded with 16 bytes, totaling 64 bytes per
393+ * point.
377394 * @return g2Result
378395 */
379396 public static G2Result g2MultiExpr (byte [] packedG2MultiExpr ) {
@@ -385,11 +402,10 @@ public static G2Result g2MultiExpr(byte[] packedG2MultiExpr) {
385402 var g2MulInput = G2MulInput .unpadMany (packedG2MultiExpr );
386403 res = new P2 (g2MulInput [0 ].g2 ).mult (g2MulInput [0 ].s );
387404 if (!res .in_group ()) {
388- return new G2Result (null ,
389- Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
405+ return new G2Result (null , Optional .of ("BLST_ERROR: Point is not in the expected subgroup" ));
390406 }
391407
392- for (int i = 1 ; i < g2MulInput .length ; i ++) {
408+ for (int i = 1 ; i < g2MulInput .length ; i ++) {
393409 // multiply
394410
395411 p2 = new P2 (g2MulInput [i ].g2 );
@@ -429,13 +445,15 @@ public static PairingResult blsPairing(byte[] packedPairing) {
429445 res .raw_aggregate (p2 , p1 );
430446 }
431447 res .commit ();
432- return new PairingResult (
433- res .finalverify () ? PAIRING_TRUE : PAIRING_FALSE , Optional .empty ());
448+ return new PairingResult (res .finalverify () ? PAIRING_TRUE : PAIRING_FALSE , Optional .empty ());
434449 } catch (Exception ex ) {
435450 return new PairingResult (PAIRING_FALSE , Optional .ofNullable (ex .getMessage ()));
436451 }
437452 }
438453
454+ /*
455+ TODO: Disabled until blst library bindings include map_to_g*
456+
439457 public static G1Result mapFpToG1(byte[] packedFp1) {
440458 try {
441459 if (!(packedFp1.length == 64)) {
@@ -474,4 +492,5 @@ public static G2Result mapFp2ToG2(byte[] packedFp2) {
474492 return new G2Result(null, Optional.ofNullable(ex.getMessage()));
475493 }
476494 }
495+ */
477496}
0 commit comments