LCOV - code coverage report
Current view: top level - ballet/zksdk/rangeproofs - fd_rangeproofs.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 208 0.0 %
Date: 2026-03-31 06:22:16 Functions: 0 2 0.0 %

          Line data    Source code
       1             : #include "fd_rangeproofs.h"
       2             : 
       3             : /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L509 */
       4             : void
       5             : fd_rangeproofs_delta(
       6             :   uchar       delta[ 32 ],
       7             :   ulong const nm,
       8             :   uchar const y[ 32 ],
       9             :   uchar const z[ 32 ],
      10             :   uchar const zz[ 32 ],
      11             :   uchar const bit_lengths[ 1 ],
      12             :   uchar const batch_len
      13           0 : ) {
      14           0 :   uchar exp_y[ 32 ];
      15           0 :   uchar sum_of_powers_y[ 32 ];
      16           0 :   fd_memcpy( exp_y, y, 32 );
      17           0 :   fd_curve25519_scalar_add( sum_of_powers_y, y, fd_curve25519_scalar_one );
      18           0 :   for( ulong i=nm; i>2; i/=2 ) {
      19           0 :     fd_curve25519_scalar_mul   ( exp_y, exp_y, exp_y );
      20           0 :     fd_curve25519_scalar_muladd( sum_of_powers_y, exp_y, sum_of_powers_y, sum_of_powers_y );
      21           0 :   }
      22           0 :   fd_curve25519_scalar_sub( delta, z, zz );
      23           0 :   fd_curve25519_scalar_mul( delta, delta, sum_of_powers_y );
      24             : 
      25           0 :   uchar neg_exp_z[ 32 ];
      26           0 :   uchar sum_2[ 32 ];
      27           0 :   fd_curve25519_scalar_neg( neg_exp_z, zz );
      28           0 :   for( ulong i=0; i<batch_len; i++ ) {
      29             :     /* sum_2 = 2^n_i - 1, encoded as a 32-byte little-endian scalar.
      30             :        https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L516 */
      31           0 :     fd_memset( sum_2, 0, 32 );
      32           0 :     fd_memset( sum_2, 0xFF, bit_lengths[i] / 8 );
      33           0 :     if( bit_lengths[i] % 8 ) {
      34           0 :       sum_2[ bit_lengths[i] / 8 ] = (uchar)( ( 1U << ( bit_lengths[i] % 8 ) ) - 1U );
      35           0 :     }
      36           0 :     fd_curve25519_scalar_mul   ( neg_exp_z, neg_exp_z, z );
      37           0 :     fd_curve25519_scalar_muladd( delta, neg_exp_z, sum_2, delta );
      38           0 :   }
      39           0 : }
      40             : 
      41             : /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L324 */
      42             : int
      43             : fd_rangeproofs_verify(
      44             :   fd_rangeproofs_range_proof_t const * range_proof,
      45             :   fd_rangeproofs_ipp_proof_t const *   ipp_proof,
      46             :   uchar const                          commitments [ 32 ],
      47             :   uchar const                          bit_lengths [ 1 ],
      48             :   uchar const                          batch_len,
      49           0 :   fd_merlin_transcript_t *             transcript ) {
      50             : 
      51             :   /*
      52             :     We need to verify a range proof, by computing a large MSM.
      53             : 
      54             :     We store points in the following array.
      55             :     Indexes are the common example of u128 batch range proof with batch_len==4,
      56             :     used in SPL confidential transfers.
      57             : 
      58             :            points
      59             :       0    G
      60             :       1    H
      61             :       2    S
      62             :       3    T_1
      63             :       4    T_2
      64             :       5    commitments[ 0 ]
      65             :            ...
      66             :       8    commitments[ 3 ]    // 4 == batch_len (example)
      67             :       9    L_vec[ 0 ]
      68             :            ...
      69             :      15    L_vec[ 6 ]          // 7 == log2( 128 )
      70             :      16    R_vec[ 0 ]
      71             :            ...
      72             :      22    R_vec[ 6 ]          // 7 == log2( 128 )
      73             :      23    generators_H[ 0 ]
      74             :            ...
      75             :     150    generators_H[ 127 ] // 128 generators
      76             :     151    generators_G[ 0 ]
      77             :            ...
      78             :     278    generators_G[ 127 ] // 128 generators
      79             :     ------------------------------------------------------ MSM
      80             :            A
      81             : 
      82             :     As final check we test that the result of the MSM == -A.
      83             :     We could negate all scalars, but that'd make it more complex to debug
      84             :     against Rust rangeproofs / Solana, in case of issues, and the marginal
      85             :     cost of negating A is negligible.
      86             : 
      87             :     This implementation has a few differences compared to the Rust implementation.
      88             : 
      89             :     - We need to support batched range proofs for u64, u128 and u256.
      90             :       Rust does dynamic allocations. This implementation statically allocates
      91             :       for u256 (a total of <64kB) and dynamically handles u64 and u128.
      92             : 
      93             :     - This implementation limits memory copies.
      94             :       Input data arrives from the Solana tx in a certain order and essentially
      95             :       includes compressed points and scalars.
      96             :       We allocate enough scalars and (uncompressed) points for the MSM.
      97             :       As we parse input data, we compute scalars and decompress points
      98             :       directly into the memory region used by MSM (layout shown above).
      99             : 
     100             :     - Points and scalars are in a different order compared to Rust,
     101             :       but their value is the same. The order has no particular meaning,
     102             :       it just seemed more convenient.
     103             : 
     104             :     - Range proof depends interally on innerproduct proof (ipp).
     105             :       ipp needs to invert logn elements (called u_i).
     106             :       range proof, in addition, needs to invert y.
     107             :       Rust uses batch inversion to invert all u_i more efficiently.
     108             :       We also include y in the batch, to save 1 inversion (~300 mul).
     109             : 
     110             :     - ipp generates n scalars s_i, from which range proof derives 2n scalars
     111             :       for generators_G and generators_H.
     112             :       The scalars for generators_G are just a rescaling of s_i,
     113             :       while the scalars for generators_H are a bit more complex.
     114             :       We store s_i in the same memory region of generators_G scalars,
     115             :       then use them to compute generators_H scalars, and finally we do
     116             :       the rescaling. This saves 8kB of stack.
     117             :   */
     118             : 
     119             :   /* Capital LOGN, N are used to allocate memory.
     120             :      Lowercase logn, n are used at runtime.
     121             :      This implementation allocates memory to support u256, and
     122             :      at runtime can verify u64, u128 and u256 range proofs. */
     123           0 : #define LOGN 8
     124           0 : #define N (1 << LOGN)
     125           0 : #define MAX (2*N + 2*LOGN + 5 + FD_RANGEPROOFS_MAX_COMMITMENTS)
     126             : 
     127           0 :   const ulong logn = ipp_proof->logn;
     128           0 :   const ulong n = 1UL << logn;
     129             : 
     130             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L330-L338
     131             :      These checks are already done in batched_range_proof_context_try_into() */
     132             : 
     133             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L340-L344
     134             :      total bit length (nm) should be a power of 2, and equal to the sz of the range proof.
     135             :      since n by definition is a power of 2, we can just check nm == n. */
     136           0 :   ulong nm = 0;
     137           0 :   for( uchar i=0; i<batch_len; i++ ) {
     138           0 :     nm += bit_lengths[i];
     139           0 :   }
     140           0 :   if( FD_UNLIKELY( nm != n ) ) {
     141           0 :     return FD_RANGEPROOFS_ERROR;
     142           0 :   }
     143             : 
     144             :   /* Validate all inputs */
     145           0 :   uchar scalars[ MAX*32 ];
     146           0 :   fd_ristretto255_point_t points[ MAX ];
     147           0 :   fd_ristretto255_point_t a_res[ 1 ];
     148           0 :   fd_ristretto255_point_t res[ 1 ];
     149             : 
     150           0 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( range_proof->tx )==NULL ) ) {
     151           0 :     return FD_RANGEPROOFS_ERROR;
     152           0 :   }
     153           0 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( range_proof->tx_blinding )==NULL ) ) {
     154           0 :     return FD_RANGEPROOFS_ERROR;
     155           0 :   }
     156           0 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( range_proof->e_blinding )==NULL ) ) {
     157           0 :     return FD_RANGEPROOFS_ERROR;
     158           0 :   }
     159           0 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( ipp_proof->a )==NULL ) ) {
     160           0 :     return FD_RANGEPROOFS_ERROR;
     161           0 :   }
     162           0 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( ipp_proof->b )==NULL ) ) {
     163           0 :     return FD_RANGEPROOFS_ERROR;
     164           0 :   }
     165             : 
     166           0 :   fd_ristretto255_point_set( &points[0], fd_rangeproofs_basepoint_G );
     167           0 :   fd_ristretto255_point_set( &points[1], fd_rangeproofs_basepoint_H );
     168           0 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( a_res, range_proof->a )==NULL ) ) {
     169           0 :     return FD_RANGEPROOFS_ERROR;
     170           0 :   }
     171           0 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], range_proof->s )==NULL ) ) {
     172           0 :     return FD_RANGEPROOFS_ERROR;
     173           0 :   }
     174           0 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], range_proof->t1 )==NULL ) ) {
     175           0 :     return FD_RANGEPROOFS_ERROR;
     176           0 :   }
     177           0 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], range_proof->t2 )==NULL ) ) {
     178           0 :     return FD_RANGEPROOFS_ERROR;
     179           0 :   }
     180           0 :   ulong idx = 5;
     181           0 :   for( ulong i=0; i<batch_len; i++, idx++ ) {
     182           0 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[ idx ], &commitments[ i*32 ] )==NULL ) ) {
     183           0 :       return FD_RANGEPROOFS_ERROR;
     184           0 :     }
     185           0 :   }
     186           0 :   for( ulong i=0; i<logn; i++, idx++ ) {
     187           0 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[ idx ], ipp_proof->vecs[ i ].l )==NULL ) ) {
     188           0 :       return FD_RANGEPROOFS_ERROR;
     189           0 :     }
     190           0 :   }
     191           0 :   for( ulong i=0; i<logn; i++, idx++ ) {
     192           0 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[ idx ], ipp_proof->vecs[ i ].r )==NULL ) ) {
     193           0 :       return FD_RANGEPROOFS_ERROR;
     194           0 :     }
     195           0 :   }
     196           0 :   fd_memcpy( &points[ idx ],   fd_rangeproofs_generators_H, n*sizeof(fd_ristretto255_point_t) );
     197           0 :   fd_memcpy( &points[ idx+n ], fd_rangeproofs_generators_G, n*sizeof(fd_ristretto255_point_t) );
     198             : 
     199             :   /* Finalize transcript and extract challenges */
     200             : 
     201             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L349 */
     202           0 :   fd_rangeproofs_transcript_domsep_range_proof( transcript, nm );
     203             : 
     204             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L351-L387 */
     205           0 :   int val = FD_TRANSCRIPT_SUCCESS;
     206           0 :   val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("A"), range_proof->a);
     207           0 :   val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("S"), range_proof->s);
     208             : 
     209             :   /* We need to invert a bunch of values, we collect them all in a single buffer to use batch inversion. */
     210           0 :   uchar batchinv_in [ 32*(1+LOGN) ];
     211           0 :   uchar batchinv_out[ 32*(1+LOGN) ];
     212           0 :   uchar allinv[ 32 ];
     213             : 
     214           0 :   uchar *y_inv = batchinv_out;
     215           0 :   uchar *y = batchinv_in;
     216           0 :   uchar z[ 32 ];
     217           0 :   fd_rangeproofs_transcript_challenge_scalar( y, transcript, FD_TRANSCRIPT_LITERAL("y") );
     218           0 :   fd_rangeproofs_transcript_challenge_scalar( z, transcript, FD_TRANSCRIPT_LITERAL("z") );
     219             : 
     220           0 :   val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("T_1"), range_proof->t1);
     221           0 :   val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("T_2"), range_proof->t2);
     222           0 :   if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
     223           0 :     return FD_RANGEPROOFS_ERROR;
     224           0 :   }
     225             : 
     226           0 :   uchar x[ 32 ];
     227           0 :   fd_rangeproofs_transcript_challenge_scalar( x, transcript, FD_TRANSCRIPT_LITERAL("x") );
     228             : 
     229           0 :   fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("t_x"), range_proof->tx);
     230           0 :   fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("t_x_blinding"), range_proof->tx_blinding);
     231           0 :   fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("e_blinding"), range_proof->e_blinding);
     232             : 
     233           0 :   uchar w[ 32 ];
     234           0 :   uchar _c[ 32 ];
     235           0 :   uchar d[ 32 ];
     236           0 :   fd_rangeproofs_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") );
     237             :   /* The challenge `c` is a legacy component from an older implementation.
     238             :      It is now unused, but is kept here for backward compatibility. */
     239           0 :   fd_rangeproofs_transcript_challenge_scalar( _c, transcript, FD_TRANSCRIPT_LITERAL("c") );
     240             : 
     241             :   /* Inner Product (sub)Proof */
     242           0 :   uchar *u =     &batchinv_in [ 32 ]; // skip y
     243           0 :   uchar *u_inv = &batchinv_out[ 32 ]; // skip y_inv
     244             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L377 */
     245           0 :   {
     246             :     /* https://github.com/solana-program/zk-elgamal-proof/blob/main/zk-sdk/src/range_proof/inner_product.rs#L246 */
     247           0 :     fd_rangeproofs_transcript_domsep_inner_product( transcript, nm );
     248             : 
     249           0 :     for( ulong i=0; i<logn; i++ ) {
     250           0 :       val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("L"), ipp_proof->vecs[ i ].l);
     251           0 :       val |= fd_rangeproofs_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("R"), ipp_proof->vecs[ i ].r);
     252           0 :       if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
     253           0 :         return FD_RANGEPROOFS_ERROR;
     254           0 :       }
     255           0 :       fd_rangeproofs_transcript_challenge_scalar( &u[ i*32 ], transcript, FD_TRANSCRIPT_LITERAL("u") );
     256           0 :     }
     257           0 :     fd_curve25519_scalar_batch_inv( batchinv_out, allinv, batchinv_in, logn+1 );
     258           0 :   }
     259             : 
     260           0 :   fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("ipp_a"), ipp_proof->a );
     261           0 :   fd_rangeproofs_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("ipp_b"), ipp_proof->b );
     262             : 
     263             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L387 */
     264           0 :   fd_rangeproofs_transcript_challenge_scalar( d, transcript, FD_TRANSCRIPT_LITERAL("d") );
     265             : 
     266             :   /* Compute scalars */
     267             : 
     268             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L391-L411 */
     269             : 
     270             :   // H: - ( eb + c t_xb )
     271           0 :   uchar const *eb = range_proof->e_blinding;
     272           0 :   uchar const *txb = range_proof->tx_blinding;
     273           0 :   fd_curve25519_scalar_muladd( &scalars[ 1*32 ], d, txb, eb );
     274           0 :   fd_curve25519_scalar_neg(    &scalars[ 1*32 ], &scalars[ 1*32 ] );
     275             : 
     276             :   // S:   x
     277             :   // T_1: c x
     278             :   // T_2: c x^2
     279           0 :   fd_curve25519_scalar_set(    &scalars[ 2*32 ], x );
     280           0 :   fd_curve25519_scalar_mul(    &scalars[ 3*32 ], d, x );
     281           0 :   fd_curve25519_scalar_mul(    &scalars[ 4*32 ], &scalars[ 3*32 ], x );
     282             : 
     283             :   // commitments: c z^2, c z^3 ...
     284           0 :   uchar zz[ 32 ];
     285           0 :   fd_curve25519_scalar_mul(    zz, z, z );
     286           0 :   fd_curve25519_scalar_mul(    &scalars[ 5*32 ], zz, d );
     287           0 :   idx = 6;
     288           0 :   for( ulong i=1; i<batch_len; i++, idx++ ) {
     289           0 :     fd_curve25519_scalar_mul(  &scalars[ idx*32 ], &scalars[ (idx-1)*32 ], z );
     290           0 :   }
     291             : 
     292             :   // L_vec: u0^2, u1^2...
     293             :   // R_vec: 1/u0^2, 1/u1^2...
     294           0 :   uchar *u_sq = &scalars[ idx*32 ];
     295           0 :   for( ulong i=0; i<logn; i++, idx++ ) {
     296           0 :     fd_curve25519_scalar_mul(  &scalars[ idx*32 ], &u[ i*32 ], &u[ i*32 ] );
     297           0 :   }
     298           0 :   for( ulong i=0; i<logn; i++, idx++ ) {
     299           0 :     fd_curve25519_scalar_mul(  &scalars[ idx*32 ], &u_inv[ i*32 ], &u_inv[ i*32 ] );
     300           0 :   }
     301             : 
     302             :   // s_i for generators_G, generators_H
     303           0 :   uchar *s = &scalars[ (idx+n)*32 ];
     304           0 :   fd_curve25519_scalar_mul( &s[ 0*32 ], allinv, y ); // allinv also contains 1/y
     305             :   // s[i] = s[ i-k ] * u[ k+1 ]^2   (k the "next power of 2" wrt i)
     306           0 :   for( ulong k=0; k<logn; k++ ) {
     307           0 :     ulong powk = (1UL << k);
     308           0 :     for( ulong j=0; j<powk; j++ ) {
     309           0 :       ulong i = powk + j;
     310           0 :       fd_curve25519_scalar_mul( &s[ i*32 ], &s[ j*32 ], &u_sq[ (logn-1-k)*32 ] );
     311           0 :     }
     312           0 :   }
     313             : 
     314             :   // generators_H: (-a * s_i) + (-z)
     315           0 :   uchar const *a = ipp_proof->a;
     316           0 :   uchar const *b = ipp_proof->b;
     317           0 :   uchar minus_b[ 32 ];
     318           0 :   uchar exp_z[ 32 ];
     319           0 :   uchar exp_y_inv[ 32 ];
     320           0 :   uchar z_and_2[ 32 ];
     321           0 :   fd_curve25519_scalar_neg( minus_b, b );
     322           0 :   fd_memcpy( exp_z, zz, 32 );
     323           0 :   fd_memcpy( z_and_2, exp_z, 32 );
     324           0 :   fd_memcpy( exp_y_inv, y, 32 ); //TODO: remove 2 unnecessary muls
     325           0 :   for( ulong i=0, j=0, m=0; i<n; i++, j++, idx++ ) {
     326           0 :     if( j == bit_lengths[m] ) {
     327           0 :       j = 0;
     328           0 :       m++;
     329           0 :       fd_curve25519_scalar_mul ( exp_z, exp_z, z );
     330           0 :       fd_memcpy( z_and_2, exp_z, 32 );
     331           0 :     }
     332           0 :     if( j != 0 ) {
     333           0 :       fd_curve25519_scalar_add ( z_and_2, z_and_2, z_and_2 );
     334           0 :     }
     335           0 :     fd_curve25519_scalar_mul   ( exp_y_inv, exp_y_inv, y_inv );
     336           0 :     fd_curve25519_scalar_muladd( &scalars[ idx*32 ], &s[ (n-1-i)*32 ], minus_b, z_and_2 );
     337           0 :     fd_curve25519_scalar_muladd( &scalars[ idx*32 ], &scalars[ idx*32 ], exp_y_inv, z );
     338           0 :   }
     339             : 
     340             :   // generators_G: (-a * s_i) + (-z)
     341           0 :   uchar minus_z[ 32 ];
     342           0 :   uchar minus_a[ 32 ];
     343           0 :   fd_curve25519_scalar_neg( minus_z, z );
     344           0 :   fd_curve25519_scalar_neg( minus_a, a );
     345           0 :   for( ulong i=0; i<n; i++, idx++ ) {
     346           0 :     fd_curve25519_scalar_muladd( &scalars[ idx*32 ], &s[ i*32 ], minus_a, minus_z );
     347           0 :   }
     348             : 
     349             :   // G
     350             :   // w * (self.t_x - a * b) + c * (delta(&bit_lengths, &y, &z) - self.t_x)
     351           0 :   uchar delta[ 32 ];
     352           0 :   fd_rangeproofs_delta( delta, nm, y, z, zz, bit_lengths, batch_len );
     353           0 :   fd_curve25519_scalar_muladd(  &scalars[ 0 ], minus_a, b, range_proof->tx );
     354           0 :   fd_curve25519_scalar_sub(     delta, delta, range_proof->tx );
     355           0 :   fd_curve25519_scalar_mul(     delta, delta, d );
     356           0 :   fd_curve25519_scalar_muladd(  &scalars[ 0 ], &scalars[ 0 ], w, delta );
     357             : 
     358             :   /* Compute the final MSM */
     359             : 
     360             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L415-L439 */
     361           0 :   fd_ristretto255_multi_scalar_mul( res, scalars, points, idx );
     362             : 
     363             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/range_proof/mod.rs#L441-L445 */
     364           0 :   if( FD_LIKELY( fd_ristretto255_point_eq_neg( res, a_res ) ) ) {
     365           0 :     return FD_RANGEPROOFS_SUCCESS;
     366           0 :   }
     367           0 :   return FD_RANGEPROOFS_ERROR;
     368           0 : #undef LOGN
     369           0 : #undef N
     370           0 : #undef MAX
     371           0 : }

Generated by: LCOV version 1.14