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 : }
|