LCOV - code coverage report
Current view: top level - flamenco/runtime/program/zksdk/instructions - fd_zksdk_ciphertext_commitment_equality.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 62 82 75.6 %
Date: 2024-11-13 11:58:15 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "../fd_zksdk_private.h"
       2             : 
       3             : static inline void
       4             : ciph_comm_eq_transcript_init( fd_zksdk_transcript_t *                 transcript,
       5          39 :                               fd_zksdk_ciph_comm_eq_context_t const * context ) {
       6          39 :   fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("ciphertext-commitment-equality-instruction") );
       7          39 :   fd_zksdk_transcript_append_pubkey    ( transcript, FD_TRANSCRIPT_LITERAL("pubkey"),     context->pubkey );
       8          39 :   fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("ciphertext"), context->ciphertext );
       9          39 :   fd_zksdk_transcript_append_commitment( transcript, FD_TRANSCRIPT_LITERAL("commitment"), context->commitment );
      10          39 : }
      11             : 
      12             : int
      13             : fd_zksdk_verify_proof_ciphertext_commitment_equality(
      14             :   fd_zksdk_ciph_comm_eq_proof_t const * proof,
      15             :   uchar const                           pubkey     [ 32 ],
      16             :   uchar const                           ciphertext [ 64 ],
      17             :   uchar const                           commitment [ 32 ],
      18          39 :   fd_zksdk_transcript_t *               transcript ) {
      19             :   /*
      20             :     We need to verify the 3 following equivalences.
      21             :     Instead of verifying them one by one, it's more efficient to pack
      22             :     them up in a single MSM (and to do so we have to mul by 1, w, w^2).
      23             : 
      24             :     (         z_s P_src =?= c H + Y_0     ) * w^2
      25             :     ( z_x G + z_s D_src =?= c C_src + Y_1 ) * w
      26             :     (     z_x G + z_r H =?= c C_dst + Y_2 ) * 1
      27             : 
      28             :     We store points and scalars in the following arrays:
      29             : 
      30             :         points  scalars
      31             :     0   G       z_x w + z_x
      32             :     1   H       z_r - c w^2
      33             :     2   Y_0     -w^2
      34             :     3   Y_1     -w
      35             :     4   P_src   z_s w^2
      36             :     5   C_src   -c w
      37             :     6   D_src   z_s w
      38             :     7   C_dst   -c
      39             :     ----------------------- MSM
      40             :         Y_2
      41             :   */
      42             : 
      43             :   /* Validate all inputs */
      44          39 :   uchar scalars[ 8 * 32 ];
      45          39 :   fd_ristretto255_point_t points[8];
      46          39 :   fd_ristretto255_point_t y2[1];
      47          39 :   fd_ristretto255_point_t res[1];
      48             : 
      49          39 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zs )==NULL ) ) {
      50           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      51           0 :   }
      52          39 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) {
      53           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      54           0 :   }
      55          39 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) {
      56           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      57           0 :   }
      58             : 
      59          39 :   fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G );
      60          39 :   fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H );
      61          39 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], proof->y0 )==NULL ) ) {
      62           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      63           0 :   }
      64          39 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], proof->y1 )==NULL ) ) {
      65           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      66           0 :   }
      67          39 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( y2, proof->y2 )==NULL ) ) {
      68           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      69           0 :   }
      70          39 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], pubkey )==NULL ) ) {
      71           3 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      72           3 :   }
      73          36 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], ciphertext )==NULL ) ) {
      74           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      75           0 :   }
      76          36 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], &ciphertext[32] )==NULL ) ) {
      77           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      78           0 :   }
      79          36 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[7], commitment )==NULL ) ) {
      80           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      81           0 :   }
      82             : 
      83             :   /* Finalize transcript and extract challenges */
      84          36 :   fd_zksdk_transcript_domsep_ciph_comm_eq_proof( transcript );
      85          36 :   int val = FD_TRANSCRIPT_SUCCESS;
      86          36 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0);
      87          36 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1);
      88          36 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2);
      89          36 :   if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
      90           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      91           0 :   }
      92             : 
      93          36 :   uchar c[ 32 ];
      94          36 :   uchar w[ 32 ];
      95          36 :   fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") );
      96          36 :   fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") );
      97             : 
      98             :   /* Compute scalars */
      99          36 :   fd_curve25519_scalar_neg(    &scalars[ 7*32 ], c );                              // -c
     100          36 :   fd_curve25519_scalar_mul(    &scalars[ 6*32 ], proof->zs, w );                   // z_s w
     101          36 :   fd_curve25519_scalar_mul(    &scalars[ 5*32 ], &scalars[ 7*32 ], w );            // -c w
     102          36 :   fd_curve25519_scalar_mul(    &scalars[ 4*32 ], &scalars[ 6*32 ], w );            // z_s w^2
     103          36 :   fd_curve25519_scalar_neg(    &scalars[ 3*32 ], w );                              // -w
     104          36 :   fd_curve25519_scalar_mul(    &scalars[ 2*32 ], &scalars[ 3*32 ], w );            // -w^2
     105          36 :   fd_curve25519_scalar_muladd( &scalars[ 1*32 ], &scalars[ 5*32 ], w, proof->zr ); // z_r - c w^2
     106          36 :   fd_curve25519_scalar_muladd( &scalars[ 0*32 ], proof->zx, w, proof->zx );        // z_x w + z_x
     107             : 
     108             :   /* Compute the final MSM */
     109          36 :   fd_ristretto255_multi_scalar_mul( res, scalars, points, 8 );
     110             : 
     111          36 :   if( FD_LIKELY( fd_ristretto255_point_eq( res, y2 ) ) ) {
     112          33 :     return FD_EXECUTOR_INSTR_SUCCESS;
     113          33 :   }
     114           3 :   return FD_ZKSDK_VERIFY_PROOF_ERROR;
     115          36 : }
     116             : 
     117             : int
     118          39 : fd_zksdk_instr_verify_proof_ciphertext_commitment_equality( void const * _context, void const * _proof ) {
     119          39 :   fd_zksdk_transcript_t transcript[1];
     120          39 :   fd_zksdk_ciph_comm_eq_context_t const * context = _context;
     121          39 :   fd_zksdk_ciph_comm_eq_proof_t const *   proof   = _proof;
     122             : 
     123          39 :   ciph_comm_eq_transcript_init( transcript, context );
     124          39 :   return fd_zksdk_verify_proof_ciphertext_commitment_equality(
     125          39 :     proof,
     126          39 :     context->pubkey,
     127          39 :     context->ciphertext,
     128          39 :     context->commitment,
     129          39 :     transcript
     130          39 :   );
     131          39 : }

Generated by: LCOV version 1.14