66} ;
77use {
88 crate :: {
9- check_program_account,
9+ check_elgamal_registry_program_account , check_program_account,
1010 error:: TokenError ,
1111 extension:: {
1212 confidential_transfer:: { instruction:: * , verify_proof:: * , * } ,
2222 instruction:: { decode_instruction_data, decode_instruction_type} ,
2323 pod:: { PodAccount , PodMint } ,
2424 processor:: Processor ,
25- proof:: verify_and_extract_context,
2625 } ,
2726 solana_program:: {
2827 account_info:: { next_account_info, AccountInfo } ,
3332 pubkey:: Pubkey ,
3433 sysvar:: Sysvar ,
3534 } ,
35+ spl_elgamal_registry:: state:: ElGamalRegistry ,
36+ spl_pod:: bytemuck:: pod_from_bytes,
3637 spl_token_confidential_transfer_proof_extraction:: {
3738 transfer:: TransferProofContext , transfer_with_fee:: TransferWithFeeProofContext ,
39+ verify_and_extract_context,
3840 } ,
3941} ;
4042
@@ -92,23 +94,59 @@ fn process_update_mint(
9294 Ok ( ( ) )
9395}
9496
97+ /// Processes a [ConfigureAccount] instruction with the assumption that an
98+ /// ElGamal registry is provided.
99+ fn process_configure_account_from_registry (
100+ program_id : & Pubkey ,
101+ accounts : & [ AccountInfo ] ,
102+ ) -> ProgramResult {
103+ let elgamal_registry_account = accounts. get ( 2 ) . ok_or ( ProgramError :: NotEnoughAccountKeys ) ?;
104+ check_elgamal_registry_program_account ( elgamal_registry_account. owner ) ?;
105+
106+ let elgamal_registry_account_data = & elgamal_registry_account. data . borrow ( ) ;
107+ let elgamal_registry_account =
108+ pod_from_bytes :: < ElGamalRegistry > ( elgamal_registry_account_data) ?;
109+
110+ let decryptable_zero_balance = PodAeCiphertext :: default ( ) ;
111+ let maximum_pending_balance_credit_counter =
112+ DEFAULT_MAXIMUM_PENDING_BALANCE_CREDIT_COUNTER . into ( ) ;
113+
114+ process_configure_account (
115+ program_id,
116+ accounts,
117+ & decryptable_zero_balance,
118+ & maximum_pending_balance_credit_counter,
119+ None ,
120+ Some ( elgamal_registry_account) ,
121+ )
122+ }
123+
95124/// Processes a [ConfigureAccount] instruction.
96125fn process_configure_account (
97126 program_id : & Pubkey ,
98127 accounts : & [ AccountInfo ] ,
99128 decryptable_zero_balance : & DecryptableBalance ,
100129 maximum_pending_balance_credit_counter : & PodU64 ,
101- proof_instruction_offset : i64 ,
130+ proof_instruction_offset : Option < i64 > ,
131+ elgamal_registry_account : Option < & ElGamalRegistry > ,
102132) -> ProgramResult {
103133 let account_info_iter = & mut accounts. iter ( ) ;
104134 let token_account_info = next_account_info ( account_info_iter) ?;
105135 let mint_info = next_account_info ( account_info_iter) ?;
106136
107- // zero-knowledge proof certifies that the supplied ElGamal public key is valid
108- let proof_context = verify_and_extract_context :: <
109- PubkeyValidityProofData ,
110- PubkeyValidityProofContext ,
111- > ( account_info_iter, proof_instruction_offset, None ) ?;
137+ let elgamal_pubkey = if let Some ( offset) = proof_instruction_offset {
138+ // zero-knowledge proof certifies that the supplied ElGamal public key is valid
139+ let proof_context = verify_and_extract_context :: <
140+ PubkeyValidityProofData ,
141+ PubkeyValidityProofContext ,
142+ > ( account_info_iter, offset, None ) ?;
143+ proof_context. pubkey
144+ } else {
145+ // if proof instruction offset is `None`, then assume that the proof
146+ // was already verified in an ElGamal registry account
147+ let _elgamal_registry_account = next_account_info ( account_info_iter) ?;
148+ elgamal_registry_account. unwrap ( ) . elgamal_pubkey
149+ } ;
112150
113151 let authority_info = next_account_info ( account_info_iter) ?;
114152 let authority_info_data_len = authority_info. data_len ( ) ;
@@ -121,13 +159,21 @@ fn process_configure_account(
121159 return Err ( TokenError :: MintMismatch . into ( ) ) ;
122160 }
123161
124- Processor :: validate_owner (
125- program_id,
126- & token_account. base . owner ,
127- authority_info,
128- authority_info_data_len,
129- account_info_iter. as_slice ( ) ,
130- ) ?;
162+ if let Some ( registry_account) = elgamal_registry_account {
163+ // if ElGamal registry was provided, then just verify that the registry owner
164+ // and the account match, then skip the signature verification check
165+ if registry_account. owner != * authority_info. key {
166+ return Err ( TokenError :: OwnerMismatch . into ( ) ) ;
167+ }
168+ } else {
169+ Processor :: validate_owner (
170+ program_id,
171+ & token_account. base . owner ,
172+ authority_info,
173+ authority_info_data_len,
174+ account_info_iter. as_slice ( ) ,
175+ ) ?;
176+ }
131177
132178 check_program_account ( mint_info. owner ) ?;
133179 let mint_data = & mut mint_info. data . borrow ( ) ;
@@ -140,7 +186,7 @@ fn process_configure_account(
140186 let confidential_transfer_account =
141187 token_account. init_extension :: < ConfidentialTransferAccount > ( false ) ?;
142188 confidential_transfer_account. approved = confidential_transfer_mint. auto_approve_new_accounts ;
143- confidential_transfer_account. elgamal_pubkey = proof_context . pubkey ;
189+ confidential_transfer_account. elgamal_pubkey = elgamal_pubkey ;
144190 confidential_transfer_account. maximum_pending_balance_credit_counter =
145191 * maximum_pending_balance_credit_counter;
146192
@@ -1102,14 +1148,20 @@ pub(crate) fn process_instruction(
11021148 }
11031149 ConfidentialTransferInstruction :: ConfigureAccount => {
11041150 msg ! ( "ConfidentialTransferInstruction::ConfigureAccount" ) ;
1105- let data = decode_instruction_data :: < ConfigureAccountInstructionData > ( input) ?;
1106- process_configure_account (
1107- program_id,
1108- accounts,
1109- & data. decryptable_zero_balance ,
1110- & data. maximum_pending_balance_credit_counter ,
1111- data. proof_instruction_offset as i64 ,
1112- )
1151+ if input. is_empty ( ) {
1152+ // instruction data is empty, so assume an ElGamal registry is provided
1153+ process_configure_account_from_registry ( program_id, accounts)
1154+ } else {
1155+ let data = decode_instruction_data :: < ConfigureAccountInstructionData > ( input) ?;
1156+ process_configure_account (
1157+ program_id,
1158+ accounts,
1159+ & data. decryptable_zero_balance ,
1160+ & data. maximum_pending_balance_credit_counter ,
1161+ Some ( data. proof_instruction_offset as i64 ) ,
1162+ None ,
1163+ )
1164+ }
11131165 }
11141166 ConfidentialTransferInstruction :: ApproveAccount => {
11151167 msg ! ( "ConfidentialTransferInstruction::ApproveAccount" ) ;
0 commit comments