@@ -109,9 +109,10 @@ pub(in crate::parse_token) fn parse_confidential_mint_burn_instruction(
109
109
} ) ;
110
110
let mut offset = 2 ;
111
111
let map = value. as_object_mut ( ) . unwrap ( ) ;
112
- if mint_data. equality_proof_instruction_offset != 0
113
- || mint_data. ciphertext_validity_proof_instruction_offset != 0
114
- || mint_data. range_proof_instruction_offset != 0
112
+ if offset < account_indexes. len ( ) - 1
113
+ && ( mint_data. equality_proof_instruction_offset != 0
114
+ || mint_data. ciphertext_validity_proof_instruction_offset != 0
115
+ || mint_data. range_proof_instruction_offset != 0 )
115
116
{
116
117
map. insert (
117
118
"instructionsSysvar" . to_string ( ) ,
@@ -189,9 +190,10 @@ pub(in crate::parse_token) fn parse_confidential_mint_burn_instruction(
189
190
} ) ;
190
191
let mut offset = 2 ;
191
192
let map = value. as_object_mut ( ) . unwrap ( ) ;
192
- if burn_data. equality_proof_instruction_offset != 0
193
- || burn_data. ciphertext_validity_proof_instruction_offset != 0
194
- || burn_data. range_proof_instruction_offset != 0
193
+ if offset < account_indexes. len ( ) - 1
194
+ && ( burn_data. equality_proof_instruction_offset != 0
195
+ || burn_data. ciphertext_validity_proof_instruction_offset != 0
196
+ || burn_data. range_proof_instruction_offset != 0 )
195
197
{
196
198
map. insert (
197
199
"instructionsSysvar" . to_string ( ) ,
@@ -254,3 +256,211 @@ pub(in crate::parse_token) fn parse_confidential_mint_burn_instruction(
254
256
}
255
257
}
256
258
}
259
+
260
+ #[ cfg( test) ]
261
+ mod test {
262
+ use {
263
+ super :: * ,
264
+ bytemuck:: Zeroable ,
265
+ solana_sdk:: {
266
+ instruction:: { AccountMeta , Instruction } ,
267
+ pubkey:: Pubkey ,
268
+ } ,
269
+ spl_token_2022:: {
270
+ extension:: confidential_mint_burn:: instruction:: {
271
+ confidential_burn_with_split_proofs, confidential_mint_with_split_proofs,
272
+ initialize_mint,
273
+ } ,
274
+ solana_program:: message:: Message ,
275
+ solana_zk_sdk:: {
276
+ encryption:: {
277
+ auth_encryption:: AeCiphertext ,
278
+ elgamal:: ElGamalPubkey ,
279
+ pod:: { auth_encryption:: PodAeCiphertext , elgamal:: PodElGamalPubkey } ,
280
+ } ,
281
+ zk_elgamal_proof_program:: proof_data:: {
282
+ BatchedGroupedCiphertext3HandlesValidityProofData , BatchedRangeProofU128Data ,
283
+ CiphertextCiphertextEqualityProofData , CiphertextCommitmentEqualityProofData ,
284
+ } ,
285
+ } ,
286
+ } ,
287
+ spl_token_confidential_transfer_proof_extraction:: instruction:: { ProofData , ProofLocation } ,
288
+ std:: num:: NonZero ,
289
+ } ;
290
+
291
+ fn check_no_panic ( mut instruction : Instruction ) {
292
+ let account_meta = AccountMeta :: new_readonly ( Pubkey :: new_unique ( ) , false ) ;
293
+ for i in 0 ..20 {
294
+ instruction. accounts = vec ! [ account_meta. clone( ) ; i] ;
295
+ let message = Message :: new ( & [ instruction. clone ( ) ] , None ) ;
296
+ let compiled_instruction = & message. instructions [ 0 ] ;
297
+ let _ = parse_token (
298
+ compiled_instruction,
299
+ & AccountKeys :: new ( & message. account_keys , None ) ,
300
+ ) ;
301
+ }
302
+ }
303
+
304
+ #[ test]
305
+ fn test_initialize ( ) {
306
+ let instruction = initialize_mint (
307
+ & spl_token_2022:: id ( ) ,
308
+ & Pubkey :: new_unique ( ) ,
309
+ PodElGamalPubkey :: default ( ) ,
310
+ PodAeCiphertext :: default ( ) ,
311
+ )
312
+ . unwrap ( ) ;
313
+ check_no_panic ( instruction) ;
314
+ }
315
+
316
+ #[ test]
317
+ fn test_update ( ) {
318
+ let instruction = update_decryptable_supply (
319
+ & spl_token_2022:: id ( ) ,
320
+ & Pubkey :: new_unique ( ) ,
321
+ & Pubkey :: new_unique ( ) ,
322
+ & [ ] ,
323
+ AeCiphertext :: default ( ) ,
324
+ )
325
+ . unwrap ( ) ;
326
+ check_no_panic ( instruction) ;
327
+ }
328
+
329
+ #[ test]
330
+ fn test_rotate ( ) {
331
+ for location in [
332
+ ProofLocation :: InstructionOffset (
333
+ NonZero :: new ( 1 ) . unwrap ( ) ,
334
+ ProofData :: InstructionData ( & CiphertextCiphertextEqualityProofData :: zeroed ( ) ) ,
335
+ ) ,
336
+ ProofLocation :: InstructionOffset (
337
+ NonZero :: new ( 1 ) . unwrap ( ) ,
338
+ ProofData :: RecordAccount ( & Pubkey :: new_unique ( ) , 0 ) ,
339
+ ) ,
340
+ ProofLocation :: ContextStateAccount ( & Pubkey :: new_unique ( ) ) ,
341
+ ] {
342
+ let instructions = rotate_supply_elgamal_pubkey (
343
+ & spl_token_2022:: id ( ) ,
344
+ & Pubkey :: new_unique ( ) ,
345
+ & Pubkey :: new_unique ( ) ,
346
+ & [ ] ,
347
+ ElGamalPubkey :: default ( ) ,
348
+ location,
349
+ )
350
+ . unwrap ( ) ;
351
+ check_no_panic ( instructions[ 0 ] . clone ( ) ) ;
352
+ }
353
+ }
354
+
355
+ #[ test]
356
+ fn test_mint ( ) {
357
+ for ( equality_proof_location, ciphertext_validity_proof_location, range_proof_location) in [
358
+ (
359
+ ProofLocation :: InstructionOffset (
360
+ NonZero :: new ( 1 ) . unwrap ( ) ,
361
+ ProofData :: InstructionData ( & CiphertextCommitmentEqualityProofData :: zeroed ( ) ) ,
362
+ ) ,
363
+ ProofLocation :: InstructionOffset (
364
+ NonZero :: new ( 2 ) . unwrap ( ) ,
365
+ ProofData :: InstructionData (
366
+ & BatchedGroupedCiphertext3HandlesValidityProofData :: zeroed ( ) ,
367
+ ) ,
368
+ ) ,
369
+ ProofLocation :: InstructionOffset (
370
+ NonZero :: new ( 3 ) . unwrap ( ) ,
371
+ ProofData :: InstructionData ( & BatchedRangeProofU128Data :: zeroed ( ) ) ,
372
+ ) ,
373
+ ) ,
374
+ (
375
+ ProofLocation :: InstructionOffset (
376
+ NonZero :: new ( 1 ) . unwrap ( ) ,
377
+ ProofData :: RecordAccount ( & Pubkey :: new_unique ( ) , 0 ) ,
378
+ ) ,
379
+ ProofLocation :: InstructionOffset (
380
+ NonZero :: new ( 2 ) . unwrap ( ) ,
381
+ ProofData :: RecordAccount ( & Pubkey :: new_unique ( ) , 0 ) ,
382
+ ) ,
383
+ ProofLocation :: InstructionOffset (
384
+ NonZero :: new ( 3 ) . unwrap ( ) ,
385
+ ProofData :: RecordAccount ( & Pubkey :: new_unique ( ) , 0 ) ,
386
+ ) ,
387
+ ) ,
388
+ (
389
+ ProofLocation :: ContextStateAccount ( & Pubkey :: new_unique ( ) ) ,
390
+ ProofLocation :: ContextStateAccount ( & Pubkey :: new_unique ( ) ) ,
391
+ ProofLocation :: ContextStateAccount ( & Pubkey :: new_unique ( ) ) ,
392
+ ) ,
393
+ ] {
394
+ let instructions = confidential_mint_with_split_proofs (
395
+ & spl_token_2022:: id ( ) ,
396
+ & Pubkey :: new_unique ( ) ,
397
+ & Pubkey :: new_unique ( ) ,
398
+ None ,
399
+ & Pubkey :: new_unique ( ) ,
400
+ & [ ] ,
401
+ equality_proof_location,
402
+ ciphertext_validity_proof_location,
403
+ range_proof_location,
404
+ AeCiphertext :: default ( ) ,
405
+ )
406
+ . unwrap ( ) ;
407
+ check_no_panic ( instructions[ 0 ] . clone ( ) ) ;
408
+ }
409
+ }
410
+
411
+ #[ test]
412
+ fn test_burn ( ) {
413
+ for ( equality_proof_location, ciphertext_validity_proof_location, range_proof_location) in [
414
+ (
415
+ ProofLocation :: InstructionOffset (
416
+ NonZero :: new ( 1 ) . unwrap ( ) ,
417
+ ProofData :: InstructionData ( & CiphertextCommitmentEqualityProofData :: zeroed ( ) ) ,
418
+ ) ,
419
+ ProofLocation :: InstructionOffset (
420
+ NonZero :: new ( 2 ) . unwrap ( ) ,
421
+ ProofData :: InstructionData (
422
+ & BatchedGroupedCiphertext3HandlesValidityProofData :: zeroed ( ) ,
423
+ ) ,
424
+ ) ,
425
+ ProofLocation :: InstructionOffset (
426
+ NonZero :: new ( 3 ) . unwrap ( ) ,
427
+ ProofData :: InstructionData ( & BatchedRangeProofU128Data :: zeroed ( ) ) ,
428
+ ) ,
429
+ ) ,
430
+ (
431
+ ProofLocation :: InstructionOffset (
432
+ NonZero :: new ( 1 ) . unwrap ( ) ,
433
+ ProofData :: RecordAccount ( & Pubkey :: new_unique ( ) , 0 ) ,
434
+ ) ,
435
+ ProofLocation :: InstructionOffset (
436
+ NonZero :: new ( 2 ) . unwrap ( ) ,
437
+ ProofData :: RecordAccount ( & Pubkey :: new_unique ( ) , 0 ) ,
438
+ ) ,
439
+ ProofLocation :: InstructionOffset (
440
+ NonZero :: new ( 3 ) . unwrap ( ) ,
441
+ ProofData :: RecordAccount ( & Pubkey :: new_unique ( ) , 0 ) ,
442
+ ) ,
443
+ ) ,
444
+ (
445
+ ProofLocation :: ContextStateAccount ( & Pubkey :: new_unique ( ) ) ,
446
+ ProofLocation :: ContextStateAccount ( & Pubkey :: new_unique ( ) ) ,
447
+ ProofLocation :: ContextStateAccount ( & Pubkey :: new_unique ( ) ) ,
448
+ ) ,
449
+ ] {
450
+ let instructions = confidential_burn_with_split_proofs (
451
+ & spl_token_2022:: id ( ) ,
452
+ & Pubkey :: new_unique ( ) ,
453
+ & Pubkey :: new_unique ( ) ,
454
+ None ,
455
+ PodAeCiphertext :: default ( ) ,
456
+ & Pubkey :: new_unique ( ) ,
457
+ & [ ] ,
458
+ equality_proof_location,
459
+ ciphertext_validity_proof_location,
460
+ range_proof_location,
461
+ )
462
+ . unwrap ( ) ;
463
+ check_no_panic ( instructions[ 0 ] . clone ( ) ) ;
464
+ }
465
+ }
466
+ }
0 commit comments