Line data Source code
1 : #include "fd_zk_elgamal_proof_program.h"
2 : #include "../fd_executor.h"
3 : #include "../fd_borrowed_account.h"
4 : #include "../fd_system_ids.h"
5 : #include "../../log_collector/fd_log_collector.h"
6 : #include "../../../ballet/zksdk/fd_zksdk.h"
7 :
8 : /* fd_zksdk_process_verify_proof is equivalent to process_verify_proof()
9 : and calls specific functions inside zksdk/instructions/ to verify each
10 : individual ZKP.
11 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L35 */
12 : int
13 0 : fd_zksdk_process_verify_proof( fd_exec_instr_ctx_t * ctx ) {
14 : /* This initial code is Firedancer-only, we just need to initialize variables.
15 : Agave code is referenced via comments. */
16 0 : int err;
17 0 : uchar const * instr_data = ctx->instr->data;
18 0 : ushort instr_acc_cnt = ctx->instr->acct_cnt;
19 0 : uchar instr_id = instr_data[0]; /* instr_data_sz already checked by the caller */
20 :
21 : /* Buffer to store ProofContextStateMeta (header) followed by a proof context
22 : (the largest context is for batched_grouped_ciphertext_3_handles_validity). */
23 0 : const ulong CTX_META_SZ = sizeof(fd_zksdk_proof_ctx_state_meta_t);
24 0 : const ulong MAX_CTX_SZ = sizeof(fd_zksdk_batched_grp_ciph_3h_val_context_t);
25 0 : uchar context_state_data[ CTX_META_SZ+MAX_CTX_SZ ];
26 :
27 : /* Specific instruction function */
28 0 : int (*fd_zksdk_instr_verify_proof)( void const *, void const * ) = NULL;
29 0 : switch( instr_id ) {
30 0 : case FD_ZKSDK_INSTR_VERIFY_ZERO_CIPHERTEXT:
31 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_zero_ciphertext;
32 0 : break;
33 0 : case FD_ZKSDK_INSTR_VERIFY_CIPHERTEXT_CIPHERTEXT_EQUALITY:
34 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_ciphertext_ciphertext_equality;
35 0 : break;
36 0 : case FD_ZKSDK_INSTR_VERIFY_CIPHERTEXT_COMMITMENT_EQUALITY:
37 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_ciphertext_commitment_equality;
38 0 : break;
39 0 : case FD_ZKSDK_INSTR_VERIFY_PUBKEY_VALIDITY:
40 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_pubkey_validity;
41 0 : break;
42 0 : case FD_ZKSDK_INSTR_VERIFY_PERCENTAGE_WITH_CAP:
43 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_percentage_with_cap;
44 0 : break;
45 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U64:
46 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_batched_range_proof_u64;
47 0 : break;
48 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U128:
49 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_batched_range_proof_u128;
50 0 : break;
51 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U256:
52 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_batched_range_proof_u256;
53 0 : break;
54 0 : case FD_ZKSDK_INSTR_VERIFY_GROUPED_CIPHERTEXT_2_HANDLES_VALIDITY:
55 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_grouped_ciphertext_2_handles_validity;
56 0 : break;
57 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_GROUPED_CIPHERTEXT_2_HANDLES_VALIDITY:
58 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_2_handles_validity;
59 0 : break;
60 0 : case FD_ZKSDK_INSTR_VERIFY_GROUPED_CIPHERTEXT_3_HANDLES_VALIDITY:
61 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_grouped_ciphertext_3_handles_validity;
62 0 : break;
63 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_GROUPED_CIPHERTEXT_3_HANDLES_VALIDITY:
64 0 : fd_zksdk_instr_verify_proof = &fd_zksdk_instr_verify_proof_batched_grouped_ciphertext_3_handles_validity;
65 0 : break;
66 0 : default:
67 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
68 0 : }
69 :
70 : /* Note: this check is redundant and can't error out
71 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L41
72 : the caller already does the same:
73 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L190 */
74 :
75 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L45 */
76 0 : ushort accessed_accounts = 0U;
77 :
78 : /* Note: instr_id is guaranteed to be valid, to access values in the arrays. */
79 0 : ulong context_sz = fd_zksdk_context_sz[instr_id];
80 0 : ulong proof_data_sz = context_sz + fd_zksdk_proof_sz[instr_id];
81 0 : uchar const * context = NULL;
82 :
83 : /* if instruction data is exactly 5 bytes, then read proof from an account
84 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L48 */
85 0 : if( ctx->instr->data_sz == FD_ZKSDK_INSTR_DATA_LENGTH_WITH_PROOF_ACCOUNT ) {
86 : /* Case 1. Proof data from account data. */
87 :
88 : /* Borrow the proof data account.
89 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L49-L50 */
90 0 : fd_guarded_borrowed_account_t proof_data_acc = {0};
91 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0UL, &proof_data_acc );
92 :
93 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L51 */
94 0 : accessed_accounts = 1U;
95 :
96 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L53-L64
97 : Note: it doesn't look like Agave code can throw any error. */
98 0 : uint proof_data_offset = fd_uint_load_4( &instr_data[1] );
99 :
100 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L65-L68
101 : Note: explcit cast to ulong just to call out that there can't be overflow */
102 0 : if( (ulong)proof_data_offset+proof_data_sz > fd_borrowed_account_get_data_len( &proof_data_acc ) ) {
103 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
104 0 : }
105 :
106 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L69-L72
107 : Note: this should never fail, the proofs are just bytes, and we tested that the size is valid */
108 0 : uchar const * proof_acc_data = fd_borrowed_account_get_data( &proof_data_acc );
109 0 : context = &proof_acc_data[proof_data_offset];
110 :
111 0 : } else {
112 : /* Case 2. Proof data from ix data. */
113 :
114 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L81-L85
115 : Note: instr_id is guaranteed to be valid, to access values in the arrays. */
116 0 : if( ctx->instr->data_sz != 1 + proof_data_sz ) {
117 0 : fd_log_collector_msg_literal( ctx, "invalid proof data" );
118 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
119 0 : }
120 0 : context = instr_data + 1;
121 0 : }
122 :
123 : /* Verify individual ZKP
124 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L74-L77
125 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L86-L89 */
126 :
127 : /* TODO: we probably need an extra check to validate the length of sigma proofs,
128 : see: https://github.com/solana-program/zk-elgamal-proof/pull/244
129 : However this check seems to be redundant for the case of ix data, and
130 : seems to be missing only for accounts. It's also unclear what the result should be,
131 : need to have explicit tests. */
132 0 : void const * proof = context + fd_zksdk_context_sz[instr_id];
133 0 : err = (*fd_zksdk_instr_verify_proof)( context, proof );
134 0 : if( FD_UNLIKELY( err ) ) {
135 : //TODO: full log, including err
136 0 : fd_log_collector_msg_literal( ctx, "proof verification failed" );
137 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
138 0 : }
139 :
140 : /* Create context state if we have both proof_context and authority accounts.
141 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L95-L98 */
142 0 : if( instr_acc_cnt >= accessed_accounts + 2U ) {
143 : /* Obtain the context_state_authority by borrowing the account temporarily in a local scope.
144 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L100-L102 */
145 0 : fd_pubkey_t context_state_authority[1];
146 0 : do {
147 0 : fd_guarded_borrowed_account_t _acc = {0};
148 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, (ushort)(accessed_accounts+1), &_acc );
149 0 : *context_state_authority = *_acc.pubkey;
150 0 : } while(0);
151 :
152 : /* Borrow the proof context account
153 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L104-L105 */
154 0 : fd_guarded_borrowed_account_t proof_context_acc = {0};
155 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, accessed_accounts, &proof_context_acc );
156 :
157 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L107-L109 */
158 0 : if( FD_UNLIKELY( !fd_memeq( fd_borrowed_account_get_owner( &proof_context_acc ), &fd_solana_zk_elgamal_proof_program_id, sizeof(fd_pubkey_t) ) ) ) {
159 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
160 0 : }
161 :
162 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L111-L112 */
163 0 : if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &proof_context_acc ) < CTX_META_SZ ) ) {
164 : /* https://github.com/solana-program/zk-elgamal-proof/blob/zk-sdk%40v5.0.1/zk-sdk/src/zk_elgamal_proof_program/state.rs#L83 */
165 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
166 0 : }
167 :
168 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L114-L116 */
169 0 : if( FD_UNLIKELY( fd_borrowed_account_get_data( &proof_context_acc )[32] != 0 ) ) {
170 0 : return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
171 0 : }
172 :
173 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L118-L119 */
174 0 : fd_memcpy( context_state_data, context_state_authority, sizeof(fd_pubkey_t) ); /* context_state_data[0..31] */
175 0 : context_state_data[ 32 ] = instr_id; /* context_state_data[32] */
176 0 : fd_memcpy( context_state_data+CTX_META_SZ, context, context_sz ); /* context_state_data[33..] */
177 :
178 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L121-L123 */
179 0 : ulong context_state_data_sx = CTX_META_SZ + context_sz;
180 0 : if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &proof_context_acc ) != context_state_data_sx ) ) {
181 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
182 0 : }
183 :
184 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L125 */
185 0 : err = fd_borrowed_account_set_data_from_slice( &proof_context_acc, context_state_data, context_state_data_sx );
186 0 : if( FD_UNLIKELY( err ) ) {
187 0 : return err;
188 0 : }
189 0 : }
190 :
191 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L126 */
192 0 : return FD_EXECUTOR_INSTR_SUCCESS;
193 0 : }
194 :
195 : /* fd_zksdk_process_close_proof_context is equivalent to process_close_proof_context()
196 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L131 */
197 : int
198 0 : fd_zksdk_process_close_proof_context( fd_exec_instr_ctx_t * ctx ) {
199 0 : #define ACC_IDX_PROOF (0UL)
200 0 : #define ACC_IDX_DEST (1UL)
201 0 : #define ACC_IDX_OWNER (2UL)
202 0 : fd_pubkey_t owner_pubkey[1];
203 0 : fd_pubkey_t proof_pubkey[1];
204 0 : fd_pubkey_t dest_pubkey[1];
205 :
206 : /* Note: this check is redundant and can't error out
207 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L133
208 : the caller already does the same:
209 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L190 */
210 :
211 : /* Obtain the owner pubkey by borrowing the owner account in local scope.
212 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L135-L141 */
213 0 : do {
214 0 : fd_guarded_borrowed_account_t owner_acc = {0};
215 0 : int instr_err_code = 0;
216 0 : if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_OWNER, &instr_err_code ) ) ) {
217 0 : if( FD_UNLIKELY( !!instr_err_code ) ) return instr_err_code;
218 0 : return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
219 0 : }
220 :
221 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_OWNER, &owner_acc );
222 0 : *owner_pubkey = *owner_acc.pubkey;
223 : /* implicit drop of borrowed owner_acc */
224 0 : } while (0);
225 :
226 : /* Allocate space for borrowed accounts */
227 0 : fd_guarded_borrowed_account_t proof_acc = {0};
228 0 : fd_guarded_borrowed_account_t dest_acc = {0};
229 :
230 : /* Obtain the proof account pubkey by borrowing the proof account.
231 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L143 */
232 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK(ctx, ACC_IDX_PROOF, &proof_acc );
233 0 : *proof_pubkey = *proof_acc.pubkey;
234 0 : fd_borrowed_account_drop( &proof_acc );
235 :
236 : /* Obtain the dest account pubkey by borrowing the dest account.
237 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L144 */
238 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_DEST, &dest_acc );
239 0 : *dest_pubkey = *dest_acc.pubkey;
240 0 : fd_borrowed_account_drop( &dest_acc );
241 :
242 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L145-L147 */
243 0 : if( FD_UNLIKELY( fd_memeq( proof_pubkey, dest_pubkey, sizeof(fd_pubkey_t) ) ) ) {
244 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
245 0 : }
246 :
247 : /* Re-borrow the proof account.
248 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L149 */
249 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK(ctx, ACC_IDX_PROOF, &proof_acc );
250 :
251 : /* Check that the proof context account is owned by the zk-elgamal-proof program.
252 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L150-L152 */
253 0 : if( FD_UNLIKELY( !fd_memeq( fd_borrowed_account_get_owner( &proof_acc ), &fd_solana_zk_elgamal_proof_program_id, sizeof(fd_pubkey_t) ) ) ) {
254 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
255 0 : }
256 :
257 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L153-L154
258 : Note: data also contains context data, but we only need the initial 33 bytes. */
259 0 : if( FD_UNLIKELY( fd_borrowed_account_get_data_len( &proof_acc ) < sizeof(fd_zksdk_proof_ctx_state_meta_t) ) ) {
260 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
261 0 : }
262 0 : fd_zksdk_proof_ctx_state_meta_t const * proof_ctx_state_meta = fd_type_pun_const( fd_borrowed_account_get_data( &proof_acc ) );
263 :
264 : /* Check that the proof context account is initialized (proof_type != 0).
265 : ProofType::Uninitialized = 0
266 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L155-L157 */
267 0 : if( FD_UNLIKELY( proof_ctx_state_meta->proof_type == 0 ) ) {
268 0 : return FD_EXECUTOR_INSTR_ERR_UNINITIALIZED_ACCOUNT;
269 0 : }
270 :
271 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L159 */
272 0 : fd_pubkey_t const * expected_owner_addr = (fd_pubkey_t const *)proof_ctx_state_meta->ctx_state_authority;
273 :
274 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L161-L163 */
275 0 : if( FD_UNLIKELY( !fd_memeq( owner_pubkey, expected_owner_addr, sizeof(fd_pubkey_t) ) ) ) {
276 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
277 0 : }
278 :
279 : /* Re-borrow the dest account.
280 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L165 */
281 0 : FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_DEST, &dest_acc );
282 :
283 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L166-L169 */
284 0 : int err = 0;
285 0 : err = fd_borrowed_account_checked_add_lamports( &dest_acc, fd_borrowed_account_get_lamports( &proof_acc ) );
286 0 : if( FD_UNLIKELY( err ) ) {
287 0 : return err;
288 0 : }
289 0 : err = fd_borrowed_account_set_lamports( &proof_acc, 0UL );
290 0 : if( FD_UNLIKELY( err ) ) {
291 0 : return err;
292 0 : }
293 0 : err = fd_borrowed_account_set_data_length( &proof_acc, 0UL );
294 0 : if( FD_UNLIKELY( err ) ) {
295 0 : return err;
296 0 : }
297 0 : err = fd_borrowed_account_set_owner( &proof_acc, &fd_solana_system_program_id );
298 0 : if( FD_UNLIKELY( err ) ) {
299 0 : return err;
300 0 : }
301 :
302 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L171 */
303 0 : return FD_EXECUTOR_INSTR_SUCCESS;
304 0 : }
305 :
306 : /*
307 : * ZK ElGamal Proof Program
308 : */
309 :
310 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L174 */
311 : int
312 0 : fd_executor_zk_elgamal_proof_program_execute( fd_exec_instr_ctx_t * ctx ) {
313 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L175-L187 */
314 0 : if( FD_LIKELY( !FD_FEATURE_ACTIVE_BANK( ctx->bank, reenable_zk_elgamal_proof_program ) ) ) {
315 0 : fd_log_collector_msg_literal( ctx, "zk-elgamal-proof program is temporarily disabled" );
316 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
317 0 : }
318 :
319 0 : uchar const * instr_data = ctx->instr->data;
320 0 : ulong instr_data_sz = ctx->instr->data_sz;
321 :
322 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L189-L193 */
323 0 : if( FD_UNLIKELY( instr_data_sz==0UL ) ) {
324 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
325 0 : }
326 :
327 0 : switch( instr_data[0] ) {
328 0 : case FD_ZKSDK_INSTR_CLOSE_CONTEXT_STATE:
329 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L196-L202 */
330 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_CLOSE_CONTEXT_STATE_COMPUTE_UNITS );
331 0 : fd_log_collector_msg_literal( ctx, "CloseContextState" );
332 0 : return fd_zksdk_process_close_proof_context( ctx );
333 :
334 0 : case FD_ZKSDK_INSTR_VERIFY_ZERO_CIPHERTEXT:
335 : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L203-L207 */
336 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_ZERO_CIPHERTEXT_COMPUTE_UNITS );
337 0 : fd_log_collector_msg_literal( ctx, "VerifyZeroCiphertext" );
338 0 : break;
339 :
340 0 : case FD_ZKSDK_INSTR_VERIFY_CIPHERTEXT_CIPHERTEXT_EQUALITY:
341 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_CIPHERTEXT_CIPHERTEXT_EQUALITY_COMPUTE_UNITS );
342 0 : fd_log_collector_msg_literal( ctx, "VerifyCiphertextCiphertextEquality" );
343 0 : break;
344 :
345 0 : case FD_ZKSDK_INSTR_VERIFY_CIPHERTEXT_COMMITMENT_EQUALITY:
346 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_CIPHERTEXT_COMMITMENT_EQUALITY_COMPUTE_UNITS );
347 0 : fd_log_collector_msg_literal( ctx, "VerifyCiphertextCommitmentEquality" );
348 0 : break;
349 :
350 0 : case FD_ZKSDK_INSTR_VERIFY_PUBKEY_VALIDITY:
351 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_PUBKEY_VALIDITY_COMPUTE_UNITS );
352 0 : fd_log_collector_msg_literal( ctx, "VerifyPubkeyValidity" );
353 0 : break;
354 :
355 0 : case FD_ZKSDK_INSTR_VERIFY_PERCENTAGE_WITH_CAP:
356 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_PERCENTAGE_WITH_CAP_COMPUTE_UNITS );
357 0 : fd_log_collector_msg_literal( ctx, "VerifyPercentageWithCap" );
358 0 : break;
359 :
360 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U64:
361 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U64_COMPUTE_UNITS );
362 0 : fd_log_collector_msg_literal( ctx, "VerifyBatchedRangeProofU64" );
363 0 : break;
364 :
365 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U128:
366 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U128_COMPUTE_UNITS );
367 0 : fd_log_collector_msg_literal( ctx, "VerifyBatchedRangeProofU128" );
368 0 : break;
369 :
370 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U256:
371 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_BATCHED_RANGE_PROOF_U256_COMPUTE_UNITS );
372 0 : fd_log_collector_msg_literal( ctx, "VerifyBatchedRangeProofU256" );
373 0 : break;
374 :
375 0 : case FD_ZKSDK_INSTR_VERIFY_GROUPED_CIPHERTEXT_2_HANDLES_VALIDITY:
376 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_GROUPED_CIPHERTEXT_2_HANDLES_VALIDITY_COMPUTE_UNITS );
377 0 : fd_log_collector_msg_literal( ctx, "VerifyGroupedCiphertext2HandlesValidity" );
378 0 : break;
379 :
380 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_GROUPED_CIPHERTEXT_2_HANDLES_VALIDITY:
381 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_BATCHED_GROUPED_CIPHERTEXT_2_HANDLES_VALIDITY_COMPUTE_UNITS );
382 0 : fd_log_collector_msg_literal( ctx, "VerifyBatchedGroupedCiphertext2HandlesValidity" );
383 0 : break;
384 :
385 0 : case FD_ZKSDK_INSTR_VERIFY_GROUPED_CIPHERTEXT_3_HANDLES_VALIDITY:
386 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_GROUPED_CIPHERTEXT_3_HANDLES_VALIDITY_COMPUTE_UNITS );
387 0 : fd_log_collector_msg_literal( ctx, "VerifyGroupedCiphertext3HandlesValidity" );
388 0 : break;
389 :
390 0 : case FD_ZKSDK_INSTR_VERIFY_BATCHED_GROUPED_CIPHERTEXT_3_HANDLES_VALIDITY:
391 0 : FD_EXEC_CU_UPDATE( ctx, FD_ZKSDK_INSTR_VERIFY_BATCHED_GROUPED_CIPHERTEXT_3_HANDLES_VALIDITY_COMPUTE_UNITS );
392 0 : fd_log_collector_msg_literal( ctx, "VerifyBatchedGroupedCiphertext3HandlesValidity" );
393 0 : break;
394 :
395 0 : default:
396 : /* Invalid instruction discriminator.
397 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L192-L193 */
398 0 : return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
399 0 : }
400 :
401 : /* All verify instructions call process_verify_proof.
402 : https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/zk-elgamal-proof/src/lib.rs#L208-L210 (and similar for each instruction) */
403 0 : return fd_zksdk_process_verify_proof( ctx );
404 0 : }
|