11use anchor_lang:: { InstructionData , ToAccountMetas } ;
2- use light_program_test:: {
3- program_test:: LightProgramTest , AddressWithTree , Indexer , ProgramTestConfig , Rpc , RpcError ,
4- } ;
5- use light_sdk:: {
6- address:: v2:: derive_address,
7- instruction:: { PackedAccounts , SystemAccountMetaConfig } ,
8- } ;
9- use solana_sdk:: {
10- instruction:: Instruction ,
11- pubkey:: Pubkey ,
12- signature:: { Keypair , Signer } ,
13- } ;
14- use nullifier:: nullifier_creation:: { NullifierInstructionData , NULLIFIER_PREFIX } ;
2+ use light_program_test:: { program_test:: LightProgramTest , Indexer , ProgramTestConfig , Rpc , RpcError } ;
3+ use solana_sdk:: { instruction:: Instruction , pubkey:: Pubkey , signature:: Signer } ;
4+ use nullifier:: nullifier_creation:: NullifierInstructionData ;
155
166#[ tokio:: test]
177async fn test_create_single_nullifier ( ) {
188 let config = ProgramTestConfig :: new ( true , Some ( vec ! [ ( "nullifier" , nullifier:: ID ) ] ) ) ;
199 let mut rpc = LightProgramTest :: new ( config) . await . unwrap ( ) ;
2010 let payer = rpc. get_payer ( ) . insecure_clone ( ) ;
2111
22- let address_tree_info = rpc. get_address_tree_v2 ( ) ;
23-
2412 let nullifier = Pubkey :: new_unique ( ) . to_bytes ( ) ;
2513
26- let ( nullifier_address, _) = derive_address (
27- & [ NULLIFIER_PREFIX , nullifier. as_slice ( ) ] ,
28- & address_tree_info. tree ,
29- & nullifier:: ID ,
30- ) ;
31-
32- let instruction = build_create_nullifier_instruction (
14+ let ( data, remaining_accounts) = build_create_nullifier_instruction_data (
3315 & mut rpc,
34- & payer,
35- & [ nullifier_address] ,
36- address_tree_info. clone ( ) ,
3716 & [ nullifier] ,
3817 )
3918 . await
4019 . unwrap ( ) ;
4120
21+ let instruction_data = nullifier:: instruction:: CreateNullifier {
22+ data,
23+ nullifiers : vec ! [ nullifier] ,
24+ } ;
25+ let accounts = nullifier:: accounts:: CreateNullifierAccounts {
26+ signer : payer. pubkey ( ) ,
27+ } ;
28+ let instruction = Instruction {
29+ program_id : nullifier:: ID ,
30+ accounts : [ accounts. to_account_metas ( None ) , remaining_accounts] . concat ( ) ,
31+ data : instruction_data. data ( ) ,
32+ } ;
33+
4234 rpc. create_and_send_transaction ( & [ instruction] , & payer. pubkey ( ) , & [ & payer] )
4335 . await
4436 . unwrap ( ) ;
4537
46- let nullifier_accounts = rpc
47- . get_compressed_accounts_by_owner ( & nullifier:: ID , None , None )
48- . await
49- . unwrap ( ) ;
50- assert_eq ! ( nullifier_accounts. value. items. len( ) , 1 ) ;
38+ assert_nullifiers_exist ( & mut rpc, & [ nullifier] ) . await ;
5139
5240 // Duplicate should fail
53- let dup_instruction = build_create_nullifier_instruction (
41+ let ( dup_data , dup_remaining_accounts ) = build_create_nullifier_instruction_data (
5442 & mut rpc,
55- & payer,
56- & [ nullifier_address] ,
57- address_tree_info,
5843 & [ nullifier] ,
5944 )
6045 . await
6146 . unwrap ( ) ;
6247
48+ let dup_instruction_data = nullifier:: instruction:: CreateNullifier {
49+ data : dup_data,
50+ nullifiers : vec ! [ nullifier] ,
51+ } ;
52+ let dup_accounts = nullifier:: accounts:: CreateNullifierAccounts {
53+ signer : payer. pubkey ( ) ,
54+ } ;
55+ let dup_instruction = Instruction {
56+ program_id : nullifier:: ID ,
57+ accounts : [ dup_accounts. to_account_metas ( None ) , dup_remaining_accounts] . concat ( ) ,
58+ data : dup_instruction_data. data ( ) ,
59+ } ;
60+
6361 let result = rpc
6462 . create_and_send_transaction ( & [ dup_instruction] , & payer. pubkey ( ) , & [ & payer] )
6563 . await ;
@@ -72,63 +70,94 @@ async fn test_create_multiple_nullifiers() {
7270 let mut rpc = LightProgramTest :: new ( config) . await . unwrap ( ) ;
7371 let payer = rpc. get_payer ( ) . insecure_clone ( ) ;
7472
75- let address_tree_info = rpc. get_address_tree_v2 ( ) ;
76-
7773 let nullifiers: Vec < [ u8 ; 32 ] > = ( 0 ..3 ) . map ( |_| Pubkey :: new_unique ( ) . to_bytes ( ) ) . collect ( ) ;
7874
79- let addresses: Vec < [ u8 ; 32 ] > = nullifiers
80- . iter ( )
81- . map ( |n| {
82- let ( addr, _) = derive_address (
83- & [ NULLIFIER_PREFIX , n. as_slice ( ) ] ,
84- & address_tree_info. tree ,
85- & nullifier:: ID ,
86- ) ;
87- addr
88- } )
89- . collect ( ) ;
90-
91- let instruction = build_create_nullifier_instruction (
75+ let ( data, remaining_accounts) = build_create_nullifier_instruction_data (
9276 & mut rpc,
93- & payer,
94- & addresses,
95- address_tree_info. clone ( ) ,
9677 & nullifiers,
9778 )
9879 . await
9980 . unwrap ( ) ;
10081
82+ let instruction_data = nullifier:: instruction:: CreateNullifier {
83+ data,
84+ nullifiers : nullifiers. clone ( ) ,
85+ } ;
86+ let accounts = nullifier:: accounts:: CreateNullifierAccounts {
87+ signer : payer. pubkey ( ) ,
88+ } ;
89+ let instruction = Instruction {
90+ program_id : nullifier:: ID ,
91+ accounts : [ accounts. to_account_metas ( None ) , remaining_accounts] . concat ( ) ,
92+ data : instruction_data. data ( ) ,
93+ } ;
94+
10195 rpc. create_and_send_transaction ( & [ instruction] , & payer. pubkey ( ) , & [ & payer] )
10296 . await
10397 . unwrap ( ) ;
10498
105- let nullifier_accounts = rpc
106- . get_compressed_accounts_by_owner ( & nullifier:: ID , None , None )
107- . await
108- . unwrap ( ) ;
109- assert_eq ! ( nullifier_accounts. value. items. len( ) , 3 ) ;
99+ assert_nullifiers_exist ( & mut rpc, & nullifiers) . await ;
110100}
111101
112- async fn build_create_nullifier_instruction < R > (
102+ async fn assert_nullifiers_exist < R > ( rpc : & mut R , nullifiers : & [ [ u8 ; 32 ] ] )
103+ where
104+ R : Rpc + Indexer ,
105+ {
106+ use light_sdk:: address:: v2:: derive_address;
107+ use nullifier:: nullifier_creation:: NULLIFIER_PREFIX ;
108+
109+ let address_tree_info = rpc. get_address_tree_v2 ( ) ;
110+
111+ for nullifier in nullifiers {
112+ let ( address, _) = derive_address (
113+ & [ NULLIFIER_PREFIX , nullifier. as_slice ( ) ] ,
114+ & address_tree_info. tree ,
115+ & nullifier:: ID ,
116+ ) ;
117+
118+ let account = rpc
119+ . get_compressed_account ( address, None )
120+ . await
121+ . expect ( "Failed to fetch compressed account" )
122+ . value ;
123+
124+ assert ! (
125+ account. is_some( ) ,
126+ "Nullifier account not found for address {:?}" ,
127+ address
128+ ) ;
129+ }
130+ }
131+
132+ async fn build_create_nullifier_instruction_data < R > (
113133 rpc : & mut R ,
114- payer : & Keypair ,
115- addresses : & [ [ u8 ; 32 ] ] ,
116- address_tree_info : light_client:: indexer:: TreeInfo ,
117134 nullifiers : & [ [ u8 ; 32 ] ] ,
118- ) -> Result < Instruction , RpcError >
135+ ) -> Result < ( NullifierInstructionData , Vec < solana_sdk :: instruction :: AccountMeta > ) , RpcError >
119136where
120137 R : Rpc + Indexer ,
121138{
139+ use light_program_test:: AddressWithTree ;
140+ use light_sdk:: { address:: v2:: derive_address, instruction:: { PackedAccounts , SystemAccountMetaConfig } } ;
141+ use nullifier:: nullifier_creation:: NULLIFIER_PREFIX ;
142+
143+ let address_tree_info = rpc. get_address_tree_v2 ( ) ;
144+
122145 let mut remaining_accounts = PackedAccounts :: default ( ) ;
123- remaining_accounts. add_pre_accounts_signer ( payer. pubkey ( ) ) ;
124146 let config = SystemAccountMetaConfig :: new ( nullifier:: ID ) ;
125147 remaining_accounts. add_system_accounts_v2 ( config) ?;
126148
127- let address_with_trees: Vec < AddressWithTree > = addresses
149+ let address_with_trees: Vec < AddressWithTree > = nullifiers
128150 . iter ( )
129- . map ( |addr| AddressWithTree {
130- address : * addr,
131- tree : address_tree_info. tree ,
151+ . map ( |n| {
152+ let ( address, _) = derive_address (
153+ & [ NULLIFIER_PREFIX , n. as_slice ( ) ] ,
154+ & address_tree_info. tree ,
155+ & nullifier:: ID ,
156+ ) ;
157+ AddressWithTree {
158+ address,
159+ tree : address_tree_info. tree ,
160+ }
132161 } )
133162 . collect ( ) ;
134163
@@ -154,18 +183,5 @@ where
154183 system_accounts_offset : system_accounts_offset as u8 ,
155184 } ;
156185
157- let instruction_data = nullifier:: instruction:: CreateNullifier {
158- data,
159- nullifiers : nullifiers. to_vec ( ) ,
160- } ;
161-
162- let accounts = nullifier:: accounts:: CreateNullifierAccounts {
163- signer : payer. pubkey ( ) ,
164- } ;
165-
166- Ok ( Instruction {
167- program_id : nullifier:: ID ,
168- accounts : [ accounts. to_account_metas ( None ) , remaining_accounts_metas] . concat ( ) ,
169- data : instruction_data. data ( ) ,
170- } )
186+ Ok ( ( data, remaining_accounts_metas) )
171187}
0 commit comments