LCOV - code coverage report
Current view: top level - ballet/bls/ref - fd_bls.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 293 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 38 0.0 %

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

Generated by: LCOV version 1.14