Line data Source code
1 : #include "../fd_zksdk_private.h"
2 :
3 : static inline void
4 : ciphertext_ciphertext_equality_transcript_init( fd_zksdk_transcript_t * transcript,
5 0 : fd_zksdk_ciph_ciph_eq_context_t const * context ) {
6 0 : fd_zksdk_transcript_init( transcript, FD_TRANSCRIPT_LITERAL("ciphertext-ciphertext-equality-instruction") );
7 0 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("first-pubkey"), context->pubkey1 );
8 0 : fd_zksdk_transcript_append_pubkey ( transcript, FD_TRANSCRIPT_LITERAL("second-pubkey"), context->pubkey2 );
9 0 : fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("first-ciphertext"), context->ciphertext1 );
10 0 : fd_zksdk_transcript_append_ciphertext( transcript, FD_TRANSCRIPT_LITERAL("second-ciphertext"), context->ciphertext2 );
11 0 : }
12 :
13 : /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/sigma_proofs/ciphertext_ciphertext_equality.rs#L136 */
14 : static inline int
15 : fd_zksdk_verify_proof_ciphertext_ciphertext_equality(
16 : fd_zksdk_ciph_ciph_eq_proof_t const * proof,
17 : uchar const pubkey1 [ 32 ],
18 : uchar const pubkey2 [ 32 ],
19 : uchar const ciphertext1[ 64 ],
20 : uchar const ciphertext2[ 64 ],
21 0 : fd_zksdk_transcript_t * transcript ) {
22 : /*
23 : We store points and scalars in the following arrays:
24 :
25 : points scalars
26 : 0 G z_x (w + ww)
27 : 1 H -c + z_r ww
28 : 2 P1 z_s
29 : 3 D1 z_s w
30 : 4 Y_1 -w
31 : 5 C1 -w c
32 : 6 Y_2 -ww
33 : 7 C2 -ww c
34 : 8 Y_3 -www
35 : 9 D2 -www c
36 : 10 P2 www z_r
37 : ------------------------ MSM
38 : Y_0
39 : */
40 :
41 : /* Validate all inputs */
42 0 : uchar scalars[ 11 * 32 ];
43 0 : fd_ristretto255_point_t points[11];
44 0 : fd_ristretto255_point_t y0[1];
45 0 : fd_ristretto255_point_t res[1];
46 :
47 0 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zs )==NULL ) ) {
48 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
49 0 : }
50 0 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zx )==NULL ) ) {
51 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
52 0 : }
53 0 : if( FD_UNLIKELY( fd_curve25519_scalar_validate( proof->zr )==NULL ) ) {
54 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
55 0 : }
56 :
57 0 : fd_ristretto255_point_set( &points[0], fd_zksdk_basepoint_G );
58 0 : fd_ristretto255_point_set( &points[1], fd_zksdk_basepoint_H );
59 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( y0, proof->y0 )==NULL ) ) {
60 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
61 0 : }
62 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[2], pubkey1 )==NULL ) ) {
63 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
64 0 : }
65 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[3], &ciphertext1[32] )==NULL ) ) {
66 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
67 0 : }
68 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[4], proof->y1 )==NULL ) ) {
69 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
70 0 : }
71 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[5], ciphertext1 )==NULL ) ) {
72 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
73 0 : }
74 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[6], proof->y2 )==NULL ) ) {
75 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
76 0 : }
77 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[7], ciphertext2 )==NULL ) ) {
78 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
79 0 : }
80 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[8], proof->y3 )==NULL ) ) {
81 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
82 0 : }
83 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[9], &ciphertext2[32] )==NULL ) ) {
84 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
85 0 : }
86 0 : if( FD_UNLIKELY( fd_ristretto255_point_decompress( &points[10], pubkey2 )==NULL ) ) {
87 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
88 0 : }
89 :
90 : /* Finalize transcript and extract challenges */
91 0 : fd_zksdk_transcript_domsep_ciph_ciph_eq_proof( transcript );
92 0 : int val = FD_TRANSCRIPT_SUCCESS;
93 0 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_0"), proof->y0);
94 0 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_1"), proof->y1);
95 0 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_2"), proof->y2);
96 0 : val |= fd_zksdk_transcript_validate_and_append_point( transcript, FD_TRANSCRIPT_LITERAL("Y_3"), proof->y3);
97 0 : if( FD_UNLIKELY( val != FD_TRANSCRIPT_SUCCESS ) ) {
98 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
99 0 : }
100 :
101 0 : uchar c[ 32 ];
102 0 : uchar w[ 32 ];
103 0 : fd_zksdk_transcript_challenge_scalar( c, transcript, FD_TRANSCRIPT_LITERAL("c") );
104 0 : fd_zksdk_transcript_challenge_scalar( w, transcript, FD_TRANSCRIPT_LITERAL("w") );
105 :
106 0 : uchar ww[ 32 ];
107 0 : fd_curve25519_scalar_mul( ww, w, w );
108 :
109 : /* Compute scalars */
110 0 : fd_curve25519_scalar_add( &scalars[ 0*32 ], w, ww ); // z_x (w + ww)
111 0 : fd_curve25519_scalar_mul( &scalars[ 0*32 ], &scalars[ 0*32 ], proof->zx );
112 0 : fd_curve25519_scalar_mul( &scalars[ 1*32 ], proof->zr, ww ); // -c + z_r ww
113 0 : fd_curve25519_scalar_sub( &scalars[ 1*32 ], &scalars[ 1*32 ], c );
114 0 : fd_curve25519_scalar_set( &scalars[ 2*32 ], proof->zs ); // z_s
115 0 : fd_curve25519_scalar_mul( &scalars[ 3*32 ], &scalars[ 2*32 ], w ); // z_s w
116 0 : fd_curve25519_scalar_neg( &scalars[ 4*32 ], w ); // -w
117 0 : fd_curve25519_scalar_mul( &scalars[ 5*32 ], &scalars[ 4*32 ], c ); // -w c
118 0 : fd_curve25519_scalar_neg( &scalars[ 6*32 ], ww ); // -ww
119 0 : fd_curve25519_scalar_mul( &scalars[ 7*32 ], &scalars[ 6*32 ], c ); // -ww c
120 0 : fd_curve25519_scalar_mul( ww, ww, w );
121 0 : fd_curve25519_scalar_neg( &scalars[ 8*32 ], ww ); // -www
122 0 : fd_curve25519_scalar_mul( &scalars[ 9*32 ], &scalars[ 8*32 ], c ); // -www c
123 0 : fd_curve25519_scalar_mul( &scalars[ 10*32 ], proof->zr, ww ); // www z_r
124 :
125 : /* Compute the final MSM */
126 0 : fd_ristretto255_multi_scalar_mul( res, scalars, points, 11 );
127 :
128 0 : if( FD_LIKELY( fd_ristretto255_point_eq( res, y0 ) ) ) {
129 0 : return FD_EXECUTOR_INSTR_SUCCESS;
130 0 : }
131 0 : return FD_ZKSDK_VERIFY_PROOF_ERROR;
132 0 : }
133 :
134 : /* https://github.com/anza-xyz/agave/blob/v2.0.1/zk-sdk/src/zk_elgamal_proof_program/proof_data/ciphertext_ciphertext_equality.rs#L105 */
135 : int
136 0 : fd_zksdk_instr_verify_proof_ciphertext_ciphertext_equality( void const * _context, void const * _proof ) {
137 0 : fd_zksdk_transcript_t transcript[1];
138 0 : fd_zksdk_ciph_ciph_eq_context_t const * context = _context;
139 0 : fd_zksdk_ciph_ciph_eq_proof_t const * proof = _proof;
140 :
141 0 : ciphertext_ciphertext_equality_transcript_init( transcript, context );
142 0 : return fd_zksdk_verify_proof_ciphertext_ciphertext_equality(
143 0 : proof,
144 0 : context->pubkey1,
145 0 : context->pubkey2,
146 0 : context->ciphertext1,
147 0 : context->ciphertext2,
148 0 : transcript
149 0 : );
150 0 : }
|