Line data Source code
1 : #include "../fd_bls.h"
2 :
3 : /* --- secret keys --- */
4 :
5 : void
6 : fd_bls_sec_to_pub( fd_bls_sec_t const * sec,
7 5403 : fd_bls_pub_t * pub ) {
8 5403 : blst_sk_to_pk_in_g1( pub, sec );
9 5403 : }
10 :
11 : void
12 : fd_bls_sec_derive( fd_bls_sec_t * sec,
13 : uchar const * ikm,
14 771 : ulong ikm_sz ) {
15 771 : FD_TEST( ikm_sz>=32UL );
16 771 : blst_keygen( sec, ikm, ikm_sz, NULL, 0UL );
17 771 : }
18 :
19 : void
20 : fd_bls_sec_sign( fd_bls_sec_t const * sec,
21 : uchar const * msg,
22 : ulong msg_sz,
23 13533 : fd_bls_sig_t * sig ) {
24 13533 : blst_p2 hash[1];
25 13533 : blst_hash_to_g2( hash, msg, msg_sz, (uchar const *)FD_BLS_DST,
26 13533 : FD_BLS_DST_SZ, NULL, 0UL );
27 13533 : blst_sign_pk_in_g1( sig, hash, sec );
28 13533 : }
29 :
30 :
31 : /* --- public keys (G1) --- */
32 :
33 : void
34 : fd_bls_pub_compress( fd_bls_pub_t const * pub,
35 4887 : uchar buf[ static FD_BLS_PUB_COMPRESSED_SZ ] ) {
36 4887 : blst_p1_affine a[1];
37 4887 : blst_p1_to_affine( a, pub );
38 4887 : blst_p1_affine_compress( buf, a );
39 4887 : }
40 :
41 : static int
42 : fd_bls_pub_from_bytes( blst_p1_affine * out,
43 : uchar const * in,
44 5763 : ulong in_sz ) {
45 5763 : BLST_ERROR err;
46 5763 : switch( in_sz ) {
47 5760 : case FD_BLS_PUB_COMPRESSED_SZ: err = blst_p1_uncompress( out, in ); break;
48 0 : case FD_BLS_PUB_SZ:
49 0 : if( FD_UNLIKELY( in[0]&0xA0U ) ) return 0;
50 0 : err = blst_p1_deserialize( out, in );
51 0 : break;
52 3 : default: return 0;
53 5763 : }
54 5760 : return err==BLST_SUCCESS &&
55 5760 : !blst_p1_affine_is_inf( out ) &&
56 5760 : blst_p1_affine_in_g1( out );
57 5763 : }
58 :
59 : int
60 : fd_bls_pub_de( fd_bls_pub_t * pub,
61 : uchar const * buf,
62 5763 : ulong buf_sz ) {
63 5763 : blst_p1_affine a[1];
64 5763 : if( FD_UNLIKELY( !fd_bls_pub_from_bytes( a, buf, buf_sz ) ) ) return -1;
65 5754 : blst_p1_from_affine( pub, a );
66 5754 : return 0;
67 5763 : }
68 :
69 : int
70 : fd_bls_pub_de_unchecked( fd_bls_pub_t * pub,
71 33 : uchar const buf[ static FD_BLS_PUB_SZ ] ) {
72 33 : blst_p1_affine a[1];
73 33 : if( FD_UNLIKELY( blst_p1_deserialize( a, buf )!=BLST_SUCCESS ) ) return -1;
74 33 : blst_p1_from_affine( pub, a );
75 33 : return 0;
76 33 : }
77 :
78 : void
79 : fd_bls_pub_add( fd_bls_pub_t * out,
80 : fd_bls_pub_t const * a,
81 11988 : fd_bls_pub_t const * b ) {
82 11988 : blst_p1_add_or_double( out, a, b );
83 11988 : }
84 :
85 : void
86 : fd_bls_pub_neg( fd_bls_pub_t * out,
87 4653 : fd_bls_pub_t const * a ) {
88 4653 : *out = *a;
89 4653 : blst_p1_cneg( out, 1 );
90 4653 : }
91 :
92 : int
93 55860 : fd_bls_pub_is_inf( fd_bls_pub_t const * pub ) {
94 55860 : return !!blst_p1_is_inf( pub );
95 55860 : }
96 :
97 : int
98 : fd_bls_pub_eq( fd_bls_pub_t const * a,
99 411 : fd_bls_pub_t const * b ) {
100 411 : return !!blst_p1_is_equal( a, b );
101 411 : }
102 :
103 : static void
104 : fd_bls_pub_add_many( fd_bls_pub_t * out,
105 : fd_bls_pub_t const * const * pubs,
106 6696 : ulong pub_cnt ) {
107 6696 : fd_bls_pub_t const * finite[ FD_BLS_SET_MAX ];
108 6696 : ulong finite_cnt = 0UL;
109 52053 : for( ulong i=0UL; i<pub_cnt; i++ )
110 45357 : if( FD_LIKELY( !fd_bls_pub_is_inf( pubs[ i ] ) ) ) finite[ finite_cnt++ ] = pubs[ i ];
111 6696 : if( FD_UNLIKELY( !finite_cnt ) ) { fd_memset( out, 0, sizeof(fd_bls_pub_t) ); return; }
112 :
113 6618 : blst_p1_affine affine [ FD_BLS_SET_MAX ];
114 6618 : blst_p1_affine const * affine_ptr[ FD_BLS_SET_MAX ];
115 6618 : blst_p1s_to_affine( affine, finite, finite_cnt );
116 51966 : for( ulong i=0UL; i<finite_cnt; i++ ) affine_ptr[ i ] = affine+i;
117 6618 : blst_p1s_add( out, affine_ptr, finite_cnt );
118 6618 : }
119 :
120 : void
121 : fd_bls_pub_sum( fd_bls_pub_t * out,
122 : fd_bls_pub_t const * pubs,
123 918 : fd_bls_set_t const * set ) {
124 918 : fd_bls_pub_t const * pub_ptr[ FD_BLS_SET_MAX ];
125 918 : ulong pub_cnt = 0UL;
126 918 : for( ulong rank = fd_bls_set_const_iter_init( set );
127 15135 : !fd_bls_set_const_iter_done( rank );
128 14217 : rank = fd_bls_set_const_iter_next( set, rank ) ) {
129 14217 : pub_ptr[ pub_cnt++ ] = pubs+rank;
130 14217 : }
131 918 : fd_bls_pub_add_many( out, pub_ptr, pub_cnt );
132 918 : }
133 :
134 : void
135 : fd_bls_pub_sum_cached( fd_bls_pub_t * out,
136 : fd_bls_pub_t const * pubs,
137 : ulong pub_cnt,
138 : fd_bls_set_t const * set,
139 213 : fd_bls_pub_t const * full ) {
140 213 : if( FD_LIKELY( !full || 2UL*fd_bls_set_cnt( set )<=pub_cnt ) ) {
141 99 : fd_bls_pub_sum( out, pubs, set );
142 99 : return;
143 99 : }
144 :
145 : /* For a dense signer set, normalize and sum only the complement, then
146 : subtract that from the cached epoch total. */
147 114 : fd_bls_pub_t const * missing[ FD_BLS_SET_MAX ];
148 114 : ulong missing_cnt = 0UL;
149 6384 : for( ulong rank=0UL; rank<pub_cnt; rank++ )
150 6270 : if( !fd_bls_set_test( set, rank ) ) missing[ missing_cnt++ ] = pubs+rank;
151 114 : fd_bls_pub_add_many( out, missing, missing_cnt );
152 114 : fd_bls_pub_neg( out, out );
153 114 : fd_bls_pub_add( out, full, out );
154 114 : }
155 :
156 : /* --- signatures (G2) --- */
157 :
158 : void
159 : fd_bls_sig_ser( fd_bls_sig_t const * sig,
160 594 : uchar buf[ static FD_BLS_SIG_SZ ] ) {
161 594 : blst_p2_affine a[1];
162 594 : blst_p2_to_affine( a, sig );
163 594 : blst_p2_affine_serialize( buf, a );
164 594 : }
165 :
166 : void
167 : fd_bls_sig_compress( fd_bls_sig_t const * sig,
168 27 : uchar buf[ static FD_BLS_SIG_COMPRESSED_SZ ] ) {
169 27 : blst_p2_affine a[1];
170 27 : blst_p2_to_affine( a, sig );
171 27 : blst_p2_affine_compress( buf, a );
172 27 : }
173 :
174 : int
175 : fd_bls_sig_de( fd_bls_sig_t * sig,
176 450 : uchar const buf[ static FD_BLS_SIG_SZ ] ) {
177 450 : blst_p2_affine a[1];
178 450 : if( FD_UNLIKELY( buf[0]&0xA0U ) ) return -1;
179 450 : if( FD_UNLIKELY( blst_p2_deserialize( a, buf )!=BLST_SUCCESS ) ) return -1;
180 450 : if( FD_UNLIKELY( !blst_p2_affine_in_g2( a ) ) ) return -1;
181 450 : blst_p2_from_affine( sig, a );
182 450 : return 0;
183 450 : }
184 :
185 : int
186 : fd_bls_sig_de_unchecked( fd_bls_sig_t * sig,
187 336 : uchar const buf[ static FD_BLS_SIG_SZ ] ) {
188 336 : blst_p2_affine a[1];
189 336 : if( FD_UNLIKELY( buf[0]&0xA0U ) ) return -1;
190 276 : if( FD_UNLIKELY( blst_p2_deserialize( a, buf )!=BLST_SUCCESS ) ) return -1;
191 273 : blst_p2_from_affine( sig, a );
192 273 : return 0;
193 276 : }
194 :
195 : int
196 : fd_bls_sig_de_compressed( fd_bls_sig_t * sig,
197 18 : uchar const buf[ static FD_BLS_SIG_COMPRESSED_SZ ] ) {
198 18 : blst_p2_affine a[1];
199 18 : if( FD_UNLIKELY( blst_p2_uncompress( a, buf )!=BLST_SUCCESS ) ) return -1;
200 15 : if( FD_UNLIKELY( !blst_p2_affine_in_g2( a ) ) ) return -1;
201 12 : blst_p2_from_affine( sig, a );
202 12 : return 0;
203 15 : }
204 :
205 : void
206 : fd_bls_sig_add( fd_bls_sig_t * out,
207 : fd_bls_sig_t const * a,
208 12099 : fd_bls_sig_t const * b ) {
209 12099 : blst_p2_add_or_double( out, a, b );
210 12099 : }
211 :
212 : void
213 : fd_bls_sig_neg( fd_bls_sig_t * out,
214 4545 : fd_bls_sig_t const * a ) {
215 4545 : *out = *a;
216 4545 : blst_p2_cneg( out, 1 );
217 4545 : }
218 :
219 : int
220 6018 : fd_bls_sig_validate( fd_bls_sig_t const * sig ) {
221 6018 : return !!blst_p2_in_g2( sig );
222 6018 : }
223 :
224 : int
225 40059 : fd_bls_sig_is_inf( fd_bls_sig_t const * sig ) {
226 40059 : return !!blst_p2_is_inf( sig );
227 40059 : }
228 :
229 : int
230 : fd_bls_sig_eq( fd_bls_sig_t const * a,
231 3 : fd_bls_sig_t const * b ) {
232 3 : return !!blst_p2_is_equal( a, b );
233 3 : }
234 :
235 : static void
236 : fd_bls_sig_add_many( fd_bls_sig_t * out,
237 : fd_bls_sig_t const * const * sigs,
238 5664 : ulong sig_cnt ) {
239 5664 : fd_bls_sig_t const * finite[ FD_BLS_SET_MAX ];
240 5664 : ulong finite_cnt = 0UL;
241 35316 : for( ulong i=0UL; i<sig_cnt; i++ )
242 29652 : if( FD_LIKELY( !fd_bls_sig_is_inf( sigs[ i ] ) ) ) finite[ finite_cnt++ ] = sigs[ i ];
243 5664 : if( FD_UNLIKELY( !finite_cnt ) ) { fd_memset( out, 0, sizeof(fd_bls_sig_t) ); return; }
244 :
245 5649 : blst_p2_affine affine [ FD_BLS_SET_MAX ];
246 5649 : blst_p2_affine const * affine_ptr[ FD_BLS_SET_MAX ];
247 5649 : blst_p2s_to_affine( affine, finite, finite_cnt );
248 35292 : for( ulong i=0UL; i<finite_cnt; i++ ) affine_ptr[ i ] = affine+i;
249 5649 : blst_p2s_add( out, affine_ptr, finite_cnt );
250 5649 : }
251 :
252 : /* --- hash-to-curve --- */
253 :
254 : void
255 : fd_bls_hash_msg( uchar const * msg,
256 : ulong msg_sz,
257 2946 : fd_bls_hash_t * hash ) {
258 2946 : blst_p2 point[1];
259 2946 : blst_hash_to_g2( point, msg, msg_sz, (uchar const *)FD_BLS_DST,
260 2946 : FD_BLS_DST_SZ, NULL, 0UL );
261 2946 : blst_p2_to_affine( hash, point );
262 2946 : }
263 :
264 : int
265 : fd_bls_hash_eq( fd_bls_hash_t const * a,
266 3 : fd_bls_hash_t const * b ) {
267 3 : return !!blst_p2_affine_is_equal( a, b );
268 3 : }
269 :
270 : static int
271 1635 : fd_bls_hash_is_inf( fd_bls_hash_t const * hash ) {
272 1635 : return !!blst_p2_affine_is_inf( hash );
273 1635 : }
274 :
275 : fd_bls_agg_t *
276 12573 : fd_bls_agg_null( fd_bls_agg_t * agg ) {
277 12573 : fd_memset( &agg->pub, 0, sizeof(fd_bls_pub_t) );
278 12573 : fd_memset( &agg->sig, 0, sizeof(fd_bls_sig_t) );
279 12573 : fd_bls_set_null( agg->set );
280 12573 : return agg;
281 12573 : }
282 :
283 : fd_bls_agg_t *
284 : fd_bls_agg_construct( fd_bls_agg_t * agg,
285 : fd_bls_pub_t const * pub,
286 : fd_bls_sig_t const * sig,
287 1317 : fd_bls_set_t const * set ) {
288 1317 : fd_bls_pub_t const * pub_ptr[ FD_BLS_SET_MAX ];
289 1317 : fd_bls_sig_t const * sig_ptr[ FD_BLS_SET_MAX ];
290 1317 : ulong cnt = 0UL;
291 1317 : fd_bls_set_copy( agg->set, set );
292 1317 : for( ulong rank = fd_bls_set_const_iter_init( set );
293 16545 : !fd_bls_set_const_iter_done( rank );
294 15228 : rank = fd_bls_set_const_iter_next( set, rank ) ) {
295 15228 : pub_ptr[ cnt ] = pub+rank;
296 15228 : sig_ptr[ cnt++ ] = sig+rank;
297 15228 : }
298 1317 : fd_bls_pub_add_many( &agg->pub, pub_ptr, cnt );
299 1317 : fd_bls_sig_add_many( &agg->sig, sig_ptr, cnt );
300 1317 : return agg;
301 1317 : }
302 :
303 : static int
304 : fd_bls_verify_hash_pair( fd_bls_hash_t const * h,
305 : fd_bls_pub_t const * pub,
306 : fd_bls_hash_t const * h_fallback,
307 : fd_bls_pub_t const * pub_fallback,
308 1572 : fd_bls_sig_t const * sig ) {
309 1572 : ulong pair_cnt = 1UL + !!pub_fallback;
310 1572 : if( FD_UNLIKELY( fd_bls_hash_is_inf( h ) || fd_bls_pub_is_inf( pub ) ||
311 1572 : (pub_fallback && (fd_bls_hash_is_inf( h_fallback ) || fd_bls_pub_is_inf( pub_fallback ))) ||
312 1572 : fd_bls_sig_is_inf( sig ) ) ) return 0;
313 :
314 1566 : blst_p1_affine p[3];
315 1566 : blst_p2_affine q[3];
316 1566 : blst_p1_to_affine( p, pub ); q[0] = *h;
317 1566 : if( pub_fallback ) { blst_p1_to_affine( p+1, pub_fallback ); q[1] = *h_fallback; }
318 1566 : p[pair_cnt] = BLS12_381_NEG_G1;
319 1566 : blst_p2_to_affine( q+pair_cnt, sig );
320 1566 : blst_p1_affine const * pp[3] = { p, p+1, p+2 };
321 1566 : blst_p2_affine const * qq[3] = { q, q+1, q+2 };
322 1566 : blst_fp12 product[1];
323 1566 : blst_miller_loop_n( product, qq, pp, pair_cnt+1UL );
324 1566 : return !!blst_fp12_finalverify( product, blst_fp12_one() );
325 1572 : }
326 :
327 : int
328 : fd_bls_agg_verify_hashed( fd_bls_hash_t const * h,
329 : fd_bls_pub_t const * pub,
330 1509 : fd_bls_sig_t const * sig ) {
331 1509 : return fd_bls_verify_hash_pair( h, pub, NULL, NULL, sig );
332 1509 : }
333 :
334 : int
335 : fd_bls_agg_verify( uchar const * msg,
336 : ulong msg_sz,
337 : fd_bls_pub_t const * pub,
338 1497 : fd_bls_sig_t const * sig ) {
339 1497 : fd_bls_hash_t h[1];
340 1497 : fd_bls_hash_msg( msg, msg_sz, h );
341 1497 : return fd_bls_agg_verify_hashed( h, pub, sig );
342 1497 : }
343 :
344 : int
345 : fd_bls_agg_verify_pair( uchar const * msg,
346 : ulong msg_sz,
347 : fd_bls_pub_t const * pub,
348 : uchar const * msg_fallback,
349 : ulong msg_fallback_sz,
350 : fd_bls_pub_t const * pub_fallback,
351 63 : fd_bls_sig_t const * sig ) {
352 63 : if( FD_UNLIKELY( !msg_fallback || !pub_fallback ) ) return 0;
353 63 : fd_bls_hash_t h[1], h_fallback[1];
354 63 : fd_bls_hash_msg( msg, msg_sz, h );
355 63 : fd_bls_hash_msg( msg_fallback, msg_fallback_sz, h_fallback );
356 63 : return fd_bls_verify_hash_pair( h, pub, h_fallback, pub_fallback, sig );
357 63 : }
358 :
359 : static void
360 : fd_bls_agg_gt( blst_fp12 * gt,
361 : fd_bls_hash_t const * h,
362 : fd_bls_pub_t const * pub,
363 5658 : fd_bls_sig_t const * sig ) {
364 5658 : blst_p1_affine p[2]; blst_p2_affine q[2];
365 5658 : blst_p1_affine const * pp[2]; blst_p2_affine const * qq[2]; ulong cnt=0UL;
366 5658 : if( FD_LIKELY( !fd_bls_pub_is_inf( pub ) ) ) {
367 5649 : blst_p1_to_affine( p+cnt,pub );
368 5649 : q[cnt]=*h; pp[cnt]=p+cnt; qq[cnt]=q+cnt;
369 5649 : cnt++;
370 5649 : }
371 5658 : if( FD_LIKELY( !fd_bls_sig_is_inf( sig ) ) ) {
372 5643 : p[cnt]=BLS12_381_NEG_G1;
373 5643 : blst_p2_to_affine( q+cnt,sig );
374 5643 : pp[cnt]=p+cnt; qq[cnt]=q+cnt;
375 5643 : cnt++;
376 5643 : }
377 5658 : if( FD_UNLIKELY( !cnt ) ) {
378 9 : *gt = *blst_fp12_one();
379 9 : return;
380 9 : }
381 5649 : blst_fp12 miller;
382 5649 : blst_miller_loop_n( &miller, qq, pp, cnt );
383 5649 : blst_final_exp( gt, &miller );
384 5649 : }
385 :
386 : /* Compute the left GT value and derive right=parent/left. */
387 : static void
388 : fd_bls_agg_bisect_run( fd_bls_hash_t const * h,
389 : fd_bls_pub_t const * const pub[],
390 : fd_bls_sig_t const * const sig[],
391 : ushort const * rank,
392 : ulong lo,
393 : ulong hi,
394 : fd_bls_pub_t const * sum_pub,
395 : fd_bls_sig_t const * sum_sig,
396 : blst_fp12 const * gt,
397 7203 : fd_bls_set_t * bad ) {
398 7203 : if( FD_UNLIKELY( hi-lo==1UL ) ) { fd_bls_set_insert(bad,rank[lo]); return; }
399 4347 : ulong mid=lo+(hi-lo)/2UL;
400 :
401 4347 : fd_bls_pub_t lpub,hpub;
402 4347 : fd_bls_sig_t lsig,hsig;
403 4347 : fd_bls_pub_add_many( &lpub,pub+lo,mid-lo );
404 4347 : fd_bls_sig_add_many( &lsig,sig+lo,mid-lo );
405 4347 : fd_bls_pub_neg( &hpub,&lpub ); fd_bls_pub_add( &hpub,&hpub,sum_pub );
406 4347 : fd_bls_sig_neg( &hsig,&lsig ); fd_bls_sig_add( &hsig,&hsig,sum_sig );
407 :
408 4347 : blst_fp12 lgt,hgt;
409 4347 : fd_bls_agg_gt( &lgt,h,&lpub,&lsig );
410 4347 : hgt = lgt;
411 4347 : blst_fp12_conjugate( &hgt );
412 4347 : blst_fp12_mul( &hgt, &hgt, gt );
413 :
414 4347 : int l_ok=blst_fp12_is_one(&lgt) && !fd_bls_pub_is_inf(&lpub) && !fd_bls_sig_is_inf(&lsig);
415 4347 : int h_ok=blst_fp12_is_one(&hgt) && !fd_bls_pub_is_inf(&hpub) && !fd_bls_sig_is_inf(&hsig);
416 4347 : if( FD_UNLIKELY(!l_ok) ) fd_bls_agg_bisect_run( h,pub,sig,rank,lo,mid,&lpub,&lsig,&lgt,bad );
417 4347 : if( FD_UNLIKELY(!h_ok) ) fd_bls_agg_bisect_run( h,pub,sig,rank,mid,hi,&hpub,&hsig,&hgt,bad );
418 4347 : }
419 :
420 : static fd_bls_set_t *
421 : fd_bls_agg_verify_bisect_hashed( fd_bls_agg_t const * agg,
422 : fd_bls_hash_t const * h,
423 : blst_fp12 const * gt,
424 : fd_bls_pub_t const * pub,
425 : fd_bls_sig_t const * sig,
426 183 : fd_bls_set_t * bad ) {
427 183 : fd_bls_set_null(bad);
428 183 : ulong cnt = fd_bls_set_cnt(agg->set);
429 183 : if( FD_UNLIKELY(!cnt) ) return bad;
430 183 : if( FD_LIKELY( blst_fp12_is_one(gt) && !fd_bls_pub_is_inf(&agg->pub) && !fd_bls_sig_is_inf(&agg->sig) ) ) return bad;
431 :
432 183 : fd_bls_pub_t const * pubs[FD_BLS_SET_MAX];
433 183 : fd_bls_sig_t const * sigs[FD_BLS_SET_MAX];
434 183 : ushort ranks[FD_BLS_SET_MAX];
435 183 : ulong n=0UL;
436 6231 : for( ulong r=fd_bls_set_const_iter_init(agg->set); !fd_bls_set_const_iter_done(r); r=fd_bls_set_const_iter_next(agg->set,r) ) {
437 6048 : pubs[n] = pub+r;
438 6048 : sigs[n] = sig+r;
439 6048 : ranks[n] = (ushort)r;
440 6048 : n++;
441 6048 : }
442 183 : fd_bls_agg_bisect_run( h,pubs,sigs,ranks,0UL,cnt,&agg->pub,&agg->sig,gt,bad );
443 183 : return bad;
444 183 : }
445 :
446 : int
447 : fd_bls_agg_verify_subtract( fd_bls_agg_t * agg,
448 : uchar const * msg,
449 : ulong msg_sz,
450 : fd_bls_pub_t const * pub,
451 : fd_bls_sig_t const * sig,
452 1311 : fd_bls_set_t * bad ) {
453 1311 : fd_bls_hash_t h; blst_fp12 gt;
454 1311 : fd_bls_hash_msg( msg, msg_sz, &h );
455 1311 : fd_bls_agg_gt( >, &h, &agg->pub, &agg->sig );
456 1311 : if( FD_LIKELY( blst_fp12_is_one( > ) && !fd_bls_pub_is_inf( &agg->pub ) && !fd_bls_sig_is_inf( &agg->sig ) ) ) {
457 1128 : fd_bls_set_null( bad );
458 1128 : return 0;
459 1128 : }
460 :
461 183 : fd_bls_agg_verify_bisect_hashed( agg, &h, >, pub, sig, bad );
462 183 : fd_bls_agg_t sub = { 0 };
463 183 : fd_bls_agg_construct( &sub, pub, sig, bad );
464 183 : fd_bls_pub_neg( &sub.pub, &sub.pub ); fd_bls_pub_add( &agg->pub, &agg->pub, &sub.pub );
465 183 : fd_bls_sig_neg( &sub.sig, &sub.sig ); fd_bls_sig_add( &agg->sig, &agg->sig, &sub.sig );
466 183 : fd_bls_set_subtract( agg->set, agg->set, bad );
467 183 : if( FD_UNLIKELY( fd_bls_pub_is_inf( &agg->pub ) ) ) return -1;
468 135 : return 0;
469 183 : }
|