LCOV - code coverage report
Current view: top level - ballet/zksdk/instructions - fd_zksdk_grouped_ciphertext_3_handles_validity.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 144 144 100.0 %
Date: 2026-10-22 18:10:43 Functions: 4 4 100.0 %

          Line data    Source code
       1             : #include "../fd_zksdk_private.h"
       2             : 
       3             : /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L299 */
       4             : static inline void
       5             : grouped_ciphertext_validity_hash_context(
       6             :   fd_zksdk_transcript_t * transcript,
       7             :   uchar const             pubkey1 [ 32 ],
       8             :   uchar const             pubkey2 [ 32 ],
       9             :   uchar const             pubkey3 [ 32 ],
      10         194 :   grp_ciph_3h_t const *   grouped_ciphertext ) {
      11         194 :   fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"),  pubkey1 );
      12         194 :   fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), pubkey2 );
      13         194 :   fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"),  pubkey3 );
      14         194 :   fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext"), (uchar *)grouped_ciphertext, sizeof(grp_ciph_3h_t) );
      15         194 : }
      16             : 
      17             : /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L163 */
      18             : static inline int
      19             : fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity(
      20             :   fd_zksdk_grp_ciph_3h_val_proof_t const * proof,
      21             :   uchar const                              pubkey1    [ 32 ],
      22             :   uchar const                              pubkey2    [ 32 ],
      23             :   uchar const                              pubkey3    [ 32 ],
      24             :   grp_ciph_3h_t const *                    grouped_ciphertext,
      25         197 :   fd_zksdk_transcript_t *                  transcript ) {
      26             : 
      27             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L174-L179 */
      28         197 :   if( FD_UNLIKELY( fd_memeq( pubkey1,                        fd_ristretto255_compressed_zero, 32 )
      29         197 :                 || fd_memeq( pubkey2,                        fd_ristretto255_compressed_zero, 32 )
      30         197 :                 || fd_memeq( grouped_ciphertext->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) {
      31           3 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      32           3 :   }
      33             : 
      34             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L181-187 */
      35         194 :   grouped_ciphertext_validity_hash_context( transcript, pubkey1, pubkey2, pubkey3, grouped_ciphertext );
      36             : 
      37             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L188-194 */
      38         194 :   return fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity(
      39         194 :     proof,
      40         194 :     pubkey1,
      41         194 :     pubkey2,
      42         194 :     pubkey3,
      43         194 :     grouped_ciphertext->commitment,
      44         194 :     grouped_ciphertext->handles[0].handle,
      45         194 :     grouped_ciphertext->handles[1].handle,
      46         194 :     grouped_ciphertext->handles[2].handle,
      47         194 :     NULL,
      48         194 :     NULL,
      49         194 :     NULL,
      50         194 :     NULL,
      51         194 :     NULL,
      52         194 :     0,
      53         194 :     transcript
      54         194 :   );
      55         197 : }
      56             : 
      57             : /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L198 */
      58             : int
      59             : fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity(
      60             :   fd_zksdk_grp_ciph_3h_val_proof_t const * proof,
      61             :   uchar const                              pubkey1    [ 32 ],
      62             :   uchar const                              pubkey2    [ 32 ],
      63             :   uchar const                              pubkey3    [ 32 ],
      64             :   uchar const                              comm       [ 32 ],
      65             :   uchar const                              handle1    [ 32 ],
      66             :   uchar const                              handle2    [ 32 ],
      67             :   uchar const                              handle3    [ 32 ],
      68             :   uchar const                              comm_hi    [ 32 ],
      69             :   uchar const                              handle1_hi [ 32 ],
      70             :   uchar const                              handle2_hi [ 32 ],
      71             :   uchar const                              handle3_hi [ 32 ],
      72             :   uchar const                              challenge_t[ 32 ],
      73             :   int   const                              batched,
      74         401 :   fd_zksdk_transcript_t *                  transcript ) {
      75             :   /*
      76             :     When batched==false, C, h1, h2 are given and C_hi, h1_hi, h2_hi, h3_hi are NULL.
      77             :     When batched==true, they are computed as C = C_lo + t C_hi.
      78             : 
      79             :     We store points and scalars in the following arrays:
      80             : 
      81             :          points  scalars
      82             :      0   G        z_x
      83             :      1   H        z_r
      84             :      2   C       -c
      85             :      3   pub1     w z_r
      86             :      4   Y_1     -w
      87             :      5   h1      -w c
      88             :      6   pub2     ww z_r
      89             :      7   Y_2     -ww
      90             :      8   h2      -ww c
      91             :      9   pub3     www z_r
      92             :     10   Y_3     -www
      93             :     11   h3      -www c
      94             :     12   C_hi    -c t      (if batched)
      95             :     13   h1_hi   -c w t    (if batched)
      96             :     14   h2_hi   -c ww t   (if batched)
      97             :     15   h3_hi   -c www t  (if batched)
      98             :     ----------------------- MSM
      99             :          Y_0
     100             :   */
     101             : 
     102             :   /* Validate all inputs */
     103         401 :   uchar scalars[ 16 * 32 ];
     104         401 :   fd_ristretto255_point_t points[16];
     105         401 :   fd_ristretto255_point_t y0[1];
     106         401 :   fd_ristretto255_point_t res[1];
     107             : 
     108         401 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) {
     109           2 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     110           2 :   }
     111         399 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) {
     112           1 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     113           1 :   }
     114             : 
     115         398 :   fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G );
     116         398 :   fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H );
     117         398 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) {
     118           2 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     119           2 :   }
     120         396 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], comm )==NULL ) ) {
     121           2 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     122           2 :   }
     123         394 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], pubkey1 )==NULL ) ) {
     124           5 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     125           5 :   }
     126         389 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], proof->y1 )==NULL ) ) {
     127           1 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     128           1 :   }
     129         388 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], handle1 )==NULL ) ) {
     130           2 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     131           2 :   }
     132         386 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], pubkey2 )==NULL ) ) {
     133           2 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     134           2 :   }
     135         384 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[7], proof->y2 )==NULL ) ) {
     136           1 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     137           1 :   }
     138         383 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[8], handle2 )==NULL ) ) {
     139           1 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     140           1 :   }
     141         382 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[9], pubkey3 )==NULL ) ) {
     142           2 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     143           2 :   }
     144         380 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[10], proof->y3 )==NULL ) ) {
     145           1 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     146           1 :   }
     147         379 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[11], handle3 )==NULL ) ) {
     148           1 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     149           1 :   }
     150             : 
     151         378 :   if (batched) {
     152         197 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[12], comm_hi )==NULL ) ) {
     153           1 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     154           1 :     }
     155         196 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[13], handle1_hi )==NULL ) ) {
     156           1 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     157           1 :     }
     158         195 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[14], handle2_hi )==NULL ) ) {
     159           1 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     160           1 :     }
     161         194 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[15], handle3_hi )==NULL ) ) {
     162           1 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     163           1 :     }
     164         194 :   }
     165             : 
     166             :   /* Finalize transcript and extract challenges */
     167             : 
     168             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L206 */
     169         374 :   fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 3 );
     170             : 
     171             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L208-L220 */
     172         374 :   int val = FD_TRANSCRIPT_SUCCESS;
     173         374 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0);
     174         374 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1);
     175         374 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2);
     176         374 :   if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
     177           4 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     178           4 :   }
     179             :   /* Y_3 can be zero */
     180         370 :   fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_3"), proof->y3);
     181             : 
     182         370 :   uchar c[ 32 ];
     183         370 :   uchar w[ 32 ];
     184         370 :   fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") );
     185             : 
     186         370 :   fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_r"), proof->zr );
     187         370 :   fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_x"), proof->zx );
     188             : 
     189         370 :   fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") );
     190             : 
     191             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L221-L290
     192             :      Note: we use a slightly different MSM but they're equivalent. */
     193             : 
     194             :   /* Compute scalars */
     195         370 :   fd_curve25519_scalar_set( &scalars[  0*32 ], proof->zx );              //  z_x
     196         370 :   fd_curve25519_scalar_set( &scalars[  1*32 ], proof->zr );              //  z_r
     197         370 :   fd_curve25519_scalar_neg( &scalars[  2*32 ], c );                      // -c
     198         370 :   fd_curve25519_scalar_mul( &scalars[  3*32 ], proof->zr, w );           //  w z_r
     199         370 :   fd_curve25519_scalar_neg( &scalars[  4*32 ], w );                      // -w
     200         370 :   fd_curve25519_scalar_mul( &scalars[  5*32 ], &scalars[ 2*32 ], w );    // -w c
     201         370 :   fd_curve25519_scalar_mul( &scalars[  6*32 ], &scalars[ 3*32 ], w );    //  ww z_r
     202         370 :   fd_curve25519_scalar_mul( &scalars[  7*32 ], &scalars[ 4*32 ], w );    // -ww
     203         370 :   fd_curve25519_scalar_mul( &scalars[  8*32 ], &scalars[ 5*32 ], w );    // -ww c
     204         370 :   fd_curve25519_scalar_mul( &scalars[  9*32 ], &scalars[ 6*32 ], w );    //  www z_r
     205         370 :   fd_curve25519_scalar_mul( &scalars[ 10*32 ], &scalars[ 7*32 ], w );    // -www
     206         370 :   fd_curve25519_scalar_mul( &scalars[ 11*32 ], &scalars[ 8*32 ], w );    // -www c
     207         370 :   if( batched ) {
     208         191 :     fd_curve25519_scalar_mul( &scalars[ 12*32 ], &scalars[  2*32 ], challenge_t ); // -c t
     209         191 :     fd_curve25519_scalar_mul( &scalars[ 13*32 ], &scalars[  5*32 ], challenge_t ); // -c w t
     210         191 :     fd_curve25519_scalar_mul( &scalars[ 14*32 ], &scalars[  8*32 ], challenge_t ); // -c ww t
     211         191 :     fd_curve25519_scalar_mul( &scalars[ 15*32 ], &scalars[ 11*32 ], challenge_t ); // -c www t
     212         191 :   }
     213             : 
     214             :   /* Compute the final MSM */
     215         370 :   fd_ristretto255_multi_scalar_mul( res, scalars, points, batched ? 16 : 12 );
     216             : 
     217             :   /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/sigma_proofs/grouped_ciphertext_validity/handles_3.rs#L292-L296 */
     218         370 :   if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) {
     219         362 :     return FD_ZKSDK_VERIFY_PROOF_SUCCESS;
     220         362 :   }
     221           8 :   return FD_ZKSDK_VERIFY_PROOF_ERROR;
     222         370 : }
     223             : 
     224             : /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/grouped_ciphertext_validity/handles_3.rs#L118 */
     225             : int
     226         197 : fd_zksdk_instr_verify_proof_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) {
     227         197 :   fd_zksdk_transcript_t transcript[1];
     228         197 :   fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-validity-3-handles-instruction") );
     229             : 
     230         197 :   fd_zksdk_grp_ciph_3h_val_context_t const * context = _context;
     231         197 :   fd_zksdk_grp_ciph_3h_val_proof_t const *   proof   = _proof;
     232         197 :   return fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity(
     233         197 :     proof,
     234         197 :     context->pubkey1,
     235         197 :     context->pubkey2,
     236         197 :     context->pubkey3,
     237         197 :     context->grouped_ciphertext,
     238         197 :     transcript
     239         197 :   );
     240         197 : }

Generated by: LCOV version 1.14