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 33 : fd_zksdk_batched_grp_ciph_3h_val_context_t const * context ) {
7 33 : fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("batched-grouped-ciphertext-validity-3-handles-instruction") );
8 33 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 );
9 33 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 );
10 33 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("third-pubkey"), context->pubkey3 );
11 33 : fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-lo"), (uchar *)&context->grouped_ciphertext_lo, sizeof(grp_ciph_3h_t) );
12 33 : fd_zksdk_transcript_append_message( transcript, FD_TRANSCRIPT_LITERAL("grouped-ciphertext-hi"), (uchar *)&context->grouped_ciphertext_hi, sizeof(grp_ciph_3h_t) );
13 33 : }
14 :
15 : int
16 : fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity(
17 : fd_zksdk_grp_ciph_3h_val_proof_t const * proof,
18 : uchar const pubkey1 [ 32 ],
19 : uchar const pubkey2 [ 32 ],
20 : uchar const pubkey3 [ 32 ],
21 : uchar const comm [ 32 ],
22 : uchar const handle1 [ 32 ],
23 : uchar const handle2 [ 32 ],
24 : uchar const handle3 [ 32 ],
25 : uchar const comm_hi [ 32 ],
26 : uchar const handle1_hi [ 32 ],
27 : uchar const handle2_hi [ 32 ],
28 : uchar const handle3_hi [ 32 ],
29 : bool const batched,
30 63 : fd_zksdk_transcript_t * transcript ) {
31 : /*
32 : When batched==false, C, h1, h2 are given and C_hi, h1_hi, h2_hi, h3_hi are NULL.
33 : When batched==true, they are computed as C = C_lo + t C_hi.
34 :
35 : We store points and scalars in the following arrays:
36 :
37 : points scalars
38 : 0 G z_x
39 : 1 H z_r
40 : 2 C -c
41 : 3 pub1 w z_r
42 : 4 Y_1 -w
43 : 5 h1 -w c
44 : 6 pub2 ww z_r
45 : 7 Y_2 -ww
46 : 8 h2 -ww c
47 : 9 pub3 www z_r
48 : 10 Y_3 -www
49 : 11 h3 -www c
50 : 12 C_hi -c t (if batched)
51 : 13 h1_hi -c w t (if batched)
52 : 14 h2_hi -c ww t (if batched)
53 : 15 h3_hi -c www t (if batched)
54 : ----------------------- MSM
55 : Y_0
56 : */
57 :
58 : /* Validate all inputs */
59 63 : uchar scalars[ 16 * 32 ];
60 63 : fd_ristretto255_point_t points[16];
61 63 : fd_ristretto255_point_t y0[1];
62 63 : fd_ristretto255_point_t res[1];
63 :
64 63 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) {
65 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
66 0 : }
67 63 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) {
68 3 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
69 3 : }
70 :
71 60 : fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G );
72 60 : fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H );
73 60 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) {
74 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
75 0 : }
76 60 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], comm )==NULL ) ) {
77 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
78 0 : }
79 60 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], pubkey1 )==NULL ) ) {
80 6 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
81 6 : }
82 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], proof->y1 )==NULL ) ) {
83 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
84 0 : }
85 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], handle1 )==NULL ) ) {
86 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
87 0 : }
88 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], pubkey2 )==NULL ) ) {
89 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
90 0 : }
91 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[7], proof->y2 )==NULL ) ) {
92 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
93 0 : }
94 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[8], handle2 )==NULL ) ) {
95 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
96 0 : }
97 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[9], pubkey3 )==NULL ) ) {
98 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
99 0 : }
100 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[10], proof->y3 )==NULL ) ) {
101 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
102 0 : }
103 54 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[11], handle3 )==NULL ) ) {
104 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
105 0 : }
106 :
107 54 : if (batched) {
108 27 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[12], comm_hi )==NULL ) ) {
109 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
110 0 : }
111 27 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[13], handle1_hi )==NULL ) ) {
112 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
113 0 : }
114 27 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[14], handle2_hi )==NULL ) ) {
115 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
116 0 : }
117 27 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[15], handle3_hi )==NULL ) ) {
118 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
119 0 : }
120 27 : }
121 :
122 : /* Finalize transcript and extract challenges */
123 54 : uchar t[ 32 ];
124 54 : if( batched ) {
125 27 : fd_zksdk_transcript_domsep_batched_grp_ciph_val_proof( transcript, 3 );
126 27 : fd_zksdk_transcript_challenge_scalar( t, transcript, FD_TRANSCRIPT_LITERAL("t") );
127 27 : }
128 :
129 54 : fd_zksdk_transcript_domsep_grp_ciph_val_proof( transcript, 3 );
130 54 : int val = FD_TRANSCRIPT_SUCCESS;
131 54 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0);
132 54 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1);
133 54 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2);
134 54 : if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
135 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
136 0 : }
137 : /* Y_3 can be zero */
138 54 : fd_zksdk_transcript_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_3"), proof->y3);
139 :
140 54 : uchar c[ 32 ];
141 54 : uchar w[ 32 ];
142 54 : fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") );
143 54 : fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") );
144 :
145 : /* Compute scalars */
146 54 : fd_curve25519_scalar_set( &scalars[ 0*32 ], proof->zx ); // z_x
147 54 : fd_curve25519_scalar_set( &scalars[ 1*32 ], proof->zr ); // z_r
148 54 : fd_curve25519_scalar_neg( &scalars[ 2*32 ], c ); // -c
149 54 : fd_curve25519_scalar_mul( &scalars[ 3*32 ], proof->zr, w ); // w z_r
150 54 : fd_curve25519_scalar_neg( &scalars[ 4*32 ], w ); // -w
151 54 : fd_curve25519_scalar_mul( &scalars[ 5*32 ], &scalars[ 2*32 ], w ); // -w c
152 54 : fd_curve25519_scalar_mul( &scalars[ 6*32 ], &scalars[ 3*32 ], w ); // ww z_r
153 54 : fd_curve25519_scalar_mul( &scalars[ 7*32 ], &scalars[ 4*32 ], w ); // -ww
154 54 : fd_curve25519_scalar_mul( &scalars[ 8*32 ], &scalars[ 5*32 ], w ); // -ww c
155 54 : fd_curve25519_scalar_mul( &scalars[ 9*32 ], &scalars[ 6*32 ], w ); // www z_r
156 54 : fd_curve25519_scalar_mul( &scalars[ 10*32 ], &scalars[ 7*32 ], w ); // -www
157 54 : fd_curve25519_scalar_mul( &scalars[ 11*32 ], &scalars[ 8*32 ], w ); // -www c
158 54 : if( batched ) {
159 27 : fd_curve25519_scalar_mul( &scalars[ 12*32 ], &scalars[ 2*32 ], t ); // -c t
160 27 : fd_curve25519_scalar_mul( &scalars[ 13*32 ], &scalars[ 5*32 ], t ); // -c w t
161 27 : fd_curve25519_scalar_mul( &scalars[ 14*32 ], &scalars[ 8*32 ], t ); // -c ww t
162 27 : fd_curve25519_scalar_mul( &scalars[ 15*32 ], &scalars[ 11*32 ], t ); // -c www t
163 27 : }
164 :
165 : /* Compute the final MSM */
166 54 : fd_ristretto255_multi_scalar_mul( res, scalars, points, batched ? 16 : 12 );
167 :
168 54 : if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) {
169 51 : return FD_EXECUTOR_INSTR_SUCCESS;
170 51 : }
171 3 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
172 54 : }
173 :
174 : int
175 33 : fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_3_handles_validity( void const * _context, void const * _proof ) {
176 33 : fd_zksdk_transcript_t transcript[1];
177 33 : fd_zksdk_batched_grp_ciph_3h_val_context_t const * context = _context;
178 33 : fd_zksdk_batched_grp_ciph_3h_val_proof_t const * proof = _proof;
179 :
180 33 : batched_grouped_ciphertext_validity_transcript_init( transcript, context );
181 33 : return fd_zksdk_verify_proof_batched_grouped_ciphertext_3_handles_validity(
182 33 : proof,
183 33 : context->pubkey1,
184 33 : context->pubkey2,
185 33 : context->pubkey3,
186 33 : context->grouped_ciphertext_lo.commitment,
187 33 : context->grouped_ciphertext_lo.handles[0].handle,
188 33 : context->grouped_ciphertext_lo.handles[1].handle,
189 33 : context->grouped_ciphertext_lo.handles[2].handle,
190 33 : context->grouped_ciphertext_hi.commitment,
191 33 : context->grouped_ciphertext_hi.handles[0].handle,
192 33 : context->grouped_ciphertext_hi.handles[1].handle,
193 33 : context->grouped_ciphertext_hi.handles[2].handle,
194 33 : true,
195 33 : transcript
196 33 : );
197 33 : }
|