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 6 : grp_ciph_3h_t const * grouped_ciphertext ) {
11 6 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), pubkey1 );
12 6 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), pubkey2 );
13 6 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"), pubkey3 );
14 6 : fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext"), (uchar *)grouped_ciphertext, sizeof(grp_ciph_3h_t) );
15 6 : }
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 6 : 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 6 : if( FD_UNLIKELY( fd_memeq( pubkey1, fd_ristretto255_compressed_zero, 32 )
29 6 : || fd_memeq( pubkey2, fd_ristretto255_compressed_zero, 32 )
30 6 : || fd_memeq( grouped_ciphertext->commitment, fd_ristretto255_compressed_zero, 32 ) ) ) {
31 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
32 0 : }
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 6 : 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 6 : return fd_zksdk_verify_proof_direct_grouped_ciphertext_3_handles_validity(
39 6 : proof,
40 6 : pubkey1,
41 6 : pubkey2,
42 6 : pubkey3,
43 6 : grouped_ciphertext->commitment,
44 6 : grouped_ciphertext->handles[0].handle,
45 6 : grouped_ciphertext->handles[1].handle,
46 6 : grouped_ciphertext->handles[2].handle,
47 6 : NULL,
48 6 : NULL,
49 6 : NULL,
50 6 : NULL,
51 6 : NULL,
52 6 : 0,
53 6 : transcript
54 6 : );
55 6 : }
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 12 : 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 12 : uchar scalars[ 16 * 32 ];
104 12 : fd_ristretto255_point_t points[16];
105 12 : fd_ristretto255_point_t y0[1];
106 12 : fd_ristretto255_point_t res[1];
107 :
108 12 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) {
109 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
110 0 : }
111 12 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) {
112 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
113 0 : }
114 :
115 12 : fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G );
116 12 : fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H );
117 12 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) {
118 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
119 0 : }
120 12 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], comm )==NULL ) ) {
121 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
122 0 : }
123 12 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], pubkey1 )==NULL ) ) {
124 2 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
125 2 : }
126 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], proof->y1 )==NULL ) ) {
127 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
128 0 : }
129 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], handle1 )==NULL ) ) {
130 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
131 0 : }
132 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], pubkey2 )==NULL ) ) {
133 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
134 0 : }
135 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[7], proof->y2 )==NULL ) ) {
136 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
137 0 : }
138 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[8], handle2 )==NULL ) ) {
139 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
140 0 : }
141 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[9], pubkey3 )==NULL ) ) {
142 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
143 0 : }
144 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[10], proof->y3 )==NULL ) ) {
145 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
146 0 : }
147 10 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[11], handle3 )==NULL ) ) {
148 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
149 0 : }
150 :
151 10 : if (batched) {
152 5 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[12], comm_hi )==NULL ) ) {
153 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
154 0 : }
155 5 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[13], handle1_hi )==NULL ) ) {
156 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
157 0 : }
158 5 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[14], handle2_hi )==NULL ) ) {
159 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
160 0 : }
161 5 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[15], handle3_hi )==NULL ) ) {
162 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
163 0 : }
164 5 : }
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 10 : 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 10 : int val = FD_TRANSCRIPT_SUCCESS;
173 10 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0);
174 10 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1);
175 10 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2);
176 10 : if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
177 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
178 0 : }
179 : /* Y_3 can be zero */
180 10 : fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_3"), proof->y3);
181 :
182 10 : uchar c[ 32 ];
183 10 : uchar w[ 32 ];
184 10 : fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") );
185 :
186 10 : fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_x"), proof->zx );
187 10 : fd_zksdk_transcript_append_scalar( transcript, FD_TRANSCRIPT_LITERAL("z_r"), proof->zr );
188 :
189 10 : 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 10 : fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->zx ); // z_x
196 10 : fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->zr ); // z_r
197 10 : fd_curve25519_scalar_neg( &scalars[ 2*32 ], c ); // -c
198 10 : fd_curve25519_scalar_mul( &scalars[ 3*32 ], proof->zr, w ); // w z_r
199 10 : fd_curve25519_scalar_neg( &scalars[ 4*32 ], w ); // -w
200 10 : fd_curve25519_scalar_mul( &scalars[ 5*32 ], &scalars[ 2*32 ], w ); // -w c
201 10 : fd_curve25519_scalar_mul( &scalars[ 6*32 ], &scalars[ 3*32 ], w ); // ww z_r
202 10 : fd_curve25519_scalar_mul( &scalars[ 7*32 ], &scalars[ 4*32 ], w ); // -ww
203 10 : fd_curve25519_scalar_mul( &scalars[ 8*32 ], &scalars[ 5*32 ], w ); // -ww c
204 10 : fd_curve25519_scalar_mul( &scalars[ 9*32 ], &scalars[ 6*32 ], w ); // www z_r
205 10 : fd_curve25519_scalar_mul( &scalars[ 10*32 ], &scalars[ 7*32 ], w ); // -www
206 10 : fd_curve25519_scalar_mul( &scalars[ 11*32 ], &scalars[ 8*32 ], w ); // -www c
207 10 : if( batched ) {
208 5 : fd_curve25519_scalar_mul( &scalars[ 12*32 ], &scalars[ 2*32 ], challenge_t ); // -c t
209 5 : fd_curve25519_scalar_mul( &scalars[ 13*32 ], &scalars[ 5*32 ], challenge_t ); // -c w t
210 5 : fd_curve25519_scalar_mul( &scalars[ 14*32 ], &scalars[ 8*32 ], challenge_t ); // -c ww t
211 5 : fd_curve25519_scalar_mul( &scalars[ 15*32 ], &scalars[ 11*32 ], challenge_t ); // -c www t
212 5 : }
213 :
214 : /* Compute the final MSM */
215 10 : 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 10 : if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) {
219 8 : return FD_ZKSDK_VERIFY_PROOF_SUCCESS;
220 8 : }
221 2 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
222 10 : }
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 6 : fd_zksdk_instr_verify_proof_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) {
227 6 : fd_zksdk_transcript_t transcript[1];
228 6 : fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-validity-3-handles-instruction") );
229 :
230 6 : fd_zksdk_grp_ciph_3h_val_context_t const * context = _context;
231 6 : fd_zksdk_grp_ciph_3h_val_proof_t const * proof = _proof;
232 6 : return fd_zksdk_verify_proof_grouped_ciphertext_3_handles_validity(
233 6 : proof,
234 6 : context->pubkey1,
235 6 : context->pubkey2,
236 6 : context->pubkey3,
237 6 : context->grouped_ciphertext,
238 6 : transcript
239 6 : );
240 6 : }
|