Line data Source code
1 : #include "../fd_zksdk_private.h" 2 : 3 : static inline void 4 : zero_ciphertext_transcript_init( fd_zksdk_transcript_t * transcript, 5 108 : fd_zksdk_zero_ciphertext_context_t const * context ) { 6 108 : fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("zero-ciphertext-instruction") ); 7 108 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("pubkey"), context->pubkey ); 8 108 : fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("ciphertext"), context->ciphertext ); 9 108 : } 10 : 11 : /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/sigma_proofs/zero_ciphertext.rs#L102 */ 12 : static inline int 13 : fd_zksdk_verify_proof_zero_ciphertext( 14 : fd_zksdk_zero_ciphertext_proof_t const * proof, 15 : uchar const pubkey [ 32 ], 16 : uchar const ciphertext[ 64 ], 17 108 : fd_zksdk_transcript_t * transcript ) { 18 : /* 19 : We need to verify the 2 following equivalences. 20 : Instead of verifying them one by one, it's more efficient to pack 21 : them up in a single MSM (and to do so we have to mul by 1, w). 22 : 23 : ( z P =?= c H + Y_P ) * 1 24 : ( z D =?= c C + Y_D ) * w 25 : 26 : We store points and scalars in the following arrays: 27 : 28 : points scalars 29 : 0 H -c 30 : 1 P z 31 : 2 C -wc 32 : 3 D wz 33 : 4 Y_D -w 34 : ----------------------- MSM 35 : Y_P 36 : */ 37 : 38 : /* Validate all inputs */ 39 108 : uchar scalars[ 5 * 32 ]; 40 108 : fd_ristretto255_point_t points[5]; 41 108 : fd_ristretto255_point_t y[1]; 42 108 : fd_ristretto255_point_t res[1]; 43 : 44 108 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->z )==NULL ) ) { 45 3 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 46 3 : } 47 : 48 105 : fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_H ); 49 105 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[1], pubkey )==NULL ) ) { 50 6 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 51 6 : } 52 99 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], &ciphertext[0] )==NULL ) ) { 53 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 54 0 : } 55 99 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], &ciphertext[32] )==NULL ) ) { 56 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 57 0 : } 58 99 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], proof->yd )==NULL ) ) { 59 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 60 0 : } 61 99 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( y, proof->yp )==NULL ) ) { 62 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 63 0 : } 64 : 65 : /* Finalize transcript and extract challenges */ 66 99 : fd_zksdk_transcript_domsep_zero_ciphertext_proof( transcript ); 67 99 : int val = FD_TRANSCRIPT_SUCCESS; 68 99 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_P"), proof->yp); 69 99 : if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) { 70 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 71 0 : } 72 99 : fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_D"), proof->yd); 73 : 74 99 : uchar c[ 32 ]; 75 99 : uchar w[ 32 ]; 76 99 : fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") ); 77 99 : fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") ); 78 : 79 : /* Compute scalars */ 80 99 : fd_curve25519_scalar_neg( &scalars[ 0*32 ], c ); // -c 81 99 : fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->z ); // z 82 99 : fd_curve25519_scalar_mul( &scalars[ 2*32 ], &scalars[ 0*32 ], w ); // -wc 83 99 : fd_curve25519_scalar_mul( &scalars[ 3*32 ], w, proof->z ); // wz 84 99 : fd_curve25519_scalar_neg( &scalars[ 4*32 ], w ); // -w 85 : 86 : /* Compute the final MSM */ 87 99 : fd_ristretto255_multi_scalar_mul( res, scalars, points, 5 ); 88 : 89 99 : if( FD_LIKELY( fd_ristretto255_point_eq( res, y ) ) ) { 90 84 : return FD_EXECUTOR_INSTR_SUCCESS; 91 84 : } 92 15 : return FD_ZKSDK_VERIFY_PROOF_ERROR; 93 99 : } 94 : 95 : /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/zero_ciphertext.rs#L81 */ 96 : int 97 108 : fd_zksdk_instr_verify_proof_zero_ciphertext( void const * _context, void const * _proof ) { 98 108 : fd_zksdk_transcript_t transcript[1]; 99 108 : fd_zksdk_zero_ciphertext_context_t const * context = _context; 100 108 : fd_zksdk_zero_ciphertext_proof_t const * proof = _proof; 101 : 102 108 : zero_ciphertext_transcript_init( transcript, context ); 103 108 : return fd_zksdk_verify_proof_zero_ciphertext( 104 108 : proof, 105 108 : context->pubkey, 106 108 : context->ciphertext, 107 108 : transcript 108 108 : ); 109 108 : }