LCOV - code coverage report
Current view: top level - flamenco/runtime/program/zksdk/instructions - fd_zksdk_batched_grouped_ciphertext_2_handles_validity.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 99 132 75.0 %
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             : batched_grouped_ciphertext_validity_transcript_init(
       5             :   fd_zksdk_transcript_t *                            transcript,
       6          39 :   fd_zksdk_batched_grp_ciph_2h_val_context_t const * context ) {
       7          39 :   fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("batched-grouped-ciphertext-validity-2-handles-instruction") );
       8          39 :   fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"),  context->pubkey1 );
       9          39 :   fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 );
      10          39 :   fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-lo"), (uchar *)&context->grouped_ciphertext_lo, sizeof(grp_ciph_2h_t) );
      11          39 :   fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)&context->grouped_ciphertext_hi, sizeof(grp_ciph_2h_t) );
      12          39 : }
      13             : 
      14             : int
      15             : fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity(
      16             :   fd_zksdk_grp_ciph_2h_val_proof_t const * proof,
      17             :   uchar const                              pubkey1    [ 32 ],
      18             :   uchar const                              pubkey2    [ 32 ],
      19             :   uchar const                              comm       [ 32 ],
      20             :   uchar const                              handle1    [ 32 ],
      21             :   uchar const                              handle2    [ 32 ],
      22             :   uchar const                              comm_hi    [ 32 ],
      23             :   uchar const                              handle1_hi [ 32 ],
      24             :   uchar const                              handle2_hi [ 32 ],
      25             :   bool const                               batched,
      26          75 :   fd_zksdk_transcript_t *                  transcript ) {
      27             :   /*
      28             :     We need to verify the 3 following equivalences.
      29             :     Instead of verifying them one by one, it's more efficient to pack
      30             :     them up in a single MSM (and to do so we have to mul by 1, w, w^2).
      31             : 
      32             :     ( z_r H + z_x G =?= c C + Y_0 ) * 1
      33             :     (      z_r pub1 =?= c h1 + Y_1 ) * w
      34             :     (      z_r pub2 =?= c h2 + Y_2 ) * w^2
      35             : 
      36             :     When batched==false, C, h1, h2 are given and C_hi, h1_hi, h2_hi are NULL.
      37             :     When batched==true, they are computed as C = C_lo + t C_hi.
      38             : 
      39             :     When pubkey2 is 0, also proof->y2, handle2 and handle2_hi should be 0.
      40             : 
      41             :     Because of batched and pubkey2_not_zero, the length of the MSM varies
      42             :     between 6 and 12.
      43             :     Points/scalars from 7 to 12 are only computed when required.
      44             : 
      45             :     We store points and scalars in the following arrays:
      46             : 
      47             :          points  scalars
      48             :      0   G       z_x
      49             :      1   H       z_r
      50             :      2   Y_1     -w
      51             :      3   Y_2     -w^2
      52             :      4   pub1    z_r w
      53             :      5   C       -c
      54             :      6   h1      -c w
      55             :      7   C_hi    -c t      (if batched)
      56             :      8   h1_hi   -c w t    (if batched)
      57             :      9   pub2    z_r w^2   (if pubkey2_not_zero)
      58             :     10   h2      -c w^2    (if pubkey2_not_zero)
      59             :     11   h2_hi   -c w^2 t  (if batched && pubkey2_not_zero)
      60             :     ----------------------- MSM
      61             :          Y_0
      62             :   */
      63             : 
      64             :   /* pubkey2 extra check: if pubkey2 is 0, then handle2,
      65             :      handle2_hi (when set) and proof->y2 must all be 0. */
      66          75 :   bool pubkey2_not_zero = true;
      67          75 :   if ( fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 ) ) {
      68           0 :     pubkey2_not_zero = false;
      69           0 :     if (
      70           0 :       !fd_memeq( handle2, fd_ristretto255_compressed_zero, 32 )
      71           0 :       || !fd_memeq( proof->y2, fd_ristretto255_compressed_zero, 32 )
      72           0 :       || ( batched && !fd_memeq( handle2_hi, fd_ristretto255_compressed_zero, 32 ) )
      73           0 :     ) {
      74           0 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
      75           0 :     }
      76           0 :   }
      77             : 
      78             :   /* Validate all inputs */
      79          75 :   uchar scalars[ 12 * 32 ];
      80          75 :   fd_ristretto255_point_t points[12];
      81          75 :   fd_ristretto255_point_t y0[1];
      82          75 :   fd_ristretto255_point_t res[1];
      83             : 
      84          75 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) {
      85           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      86           0 :   }
      87          75 :   if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) {
      88           3 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      89           3 :   }
      90             : 
      91          72 :   fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G );
      92          72 :   fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H );
      93          72 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) {
      94           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      95           0 :   }
      96          72 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], proof->y1 )==NULL ) ) {
      97           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
      98           0 :   }
      99          72 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], proof->y2 )==NULL ) ) {
     100           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     101           0 :   }
     102          72 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], pubkey1 )==NULL ) ) {
     103           6 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     104           6 :   }
     105          66 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], comm )==NULL ) ) {
     106           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     107           0 :   }
     108          66 :   if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], handle1 )==NULL ) ) {
     109           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     110           0 :   }
     111             : 
     112          66 :   ulong idx = 7;
     113          66 :   if( batched ) {
     114          36 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], comm_hi )==NULL ) ) {
     115           0 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     116           0 :     }
     117          36 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle1_hi )==NULL ) ) {
     118           0 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     119           0 :     }
     120          36 :   }
     121             : 
     122          66 :   if( pubkey2_not_zero ) {
     123          66 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], pubkey2 )==NULL ) ) {
     124           0 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     125           0 :     }
     126          66 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle2 )==NULL ) ) {
     127           0 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     128           0 :     }
     129          66 :   }
     130             : 
     131          66 :   if( batched && pubkey2_not_zero ) {
     132          36 :     if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[idx++], handle2_hi )==NULL ) ) {
     133           0 :       return FD_ZKSDK_VERIFY_PROOF_ERROR;
     134           0 :     }
     135          36 :   }
     136             : 
     137             :   /* Finalize transcript and extract challenges */
     138          66 :   uchar t[ 32 ];
     139          66 :   if( batched ) {
     140          36 :     fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 2 );
     141          36 :     fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") );
     142          36 :   }
     143             : 
     144          66 :   fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 2 );
     145          66 :   int val = FD_TRANSCRIPT_SUCCESS;
     146          66 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0);
     147          66 :   val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1);
     148          66 :   if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
     149           0 :     return FD_ZKSDK_VERIFY_PROOF_ERROR;
     150           0 :   }
     151             :   /* Y_2 can be an all zero point if the pubkey2 is all zero */
     152          66 :   fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2);
     153             : 
     154          66 :   uchar c[ 32 ];
     155          66 :   uchar w[ 32 ];
     156          66 :   fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") );
     157          66 :   fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") );
     158             : 
     159             :   /* Compute scalars */
     160          66 :   fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->zx );           //  z_x
     161          66 :   fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->zr );           //  z_r
     162          66 :   fd_curve25519_scalar_neg( &scalars[ 2*32 ], w );                   // -w
     163          66 :   fd_curve25519_scalar_mul( &scalars[ 3*32 ], &scalars[ 2*32 ], w ); // -w^2
     164          66 :   fd_curve25519_scalar_mul( &scalars[ 4*32 ], proof->zr, w );        //  z_r w
     165          66 :   fd_curve25519_scalar_neg( &scalars[ 5*32 ], c );                   // -c
     166          66 :   fd_curve25519_scalar_mul( &scalars[ 6*32 ], &scalars[ 5*32 ], w ); // -c w
     167          66 :   idx = 7;
     168          66 :   if( batched ) {
     169          36 :     fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 5*32 ], t ); // -c t
     170          36 :     fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 6*32 ], t ); // -c w t
     171          36 :   }
     172          66 :   if( pubkey2_not_zero ) {
     173          66 :     fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 4*32 ], w ); // z_r w^2
     174          66 :     fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 6*32 ], w ); // -c w^2
     175          66 :   }
     176          66 :   if( batched && pubkey2_not_zero ) {
     177          36 :     fd_curve25519_scalar_mul( &scalars[ (idx++)*32 ], &scalars[ 8*32 ], w ); // -c w^2 t
     178          36 :   }
     179             : 
     180             :   /* Compute the final MSM */
     181          66 :   fd_ristretto255_multi_scalar_mul( res, scalars, points, idx );
     182             : 
     183          66 :   if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) {
     184          63 :     return FD_EXECUTOR_INSTR_SUCCESS;
     185          63 :   }
     186           3 :   return FD_ZKSDK_VERIFY_PROOF_ERROR;
     187          66 : }
     188             : 
     189             : int
     190          39 : fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_2_handles_validity( void const * _context, void const * _proof ) {
     191          39 :   fd_zksdk_transcript_t transcript[1];
     192          39 :   fd_zksdk_batched_grp_ciph_2h_val_context_t const * context = _context;
     193          39 :   fd_zksdk_batched_grp_ciph_2h_val_proof_t const *   proof   = _proof;
     194             : 
     195          39 :   batched_grouped_ciphertext_validity_transcript_init( transcript, context );
     196          39 :   return fd_zksdk_verify_proof_batched_grouped_ciphertext_2_handles_validity(
     197          39 :     proof,
     198          39 :     context->pubkey1,
     199          39 :     context->pubkey2,
     200          39 :     context->grouped_ciphertext_lo.commitment,
     201          39 :     context->grouped_ciphertext_lo.handles[0].handle,
     202          39 :     context->grouped_ciphertext_lo.handles[1].handle,
     203          39 :     context->grouped_ciphertext_hi.commitment,
     204          39 :     context->grouped_ciphertext_hi.handles[0].handle,
     205          39 :     context->grouped_ciphertext_hi.handles[1].handle,
     206          39 :     true,
     207          39 :     transcript
     208          39 :   );
     209          39 : }

Generated by: LCOV version 1.14