11use {
22 super :: ConfidentialMintBurn ,
3- crate :: error:: TokenError ,
3+ crate :: {
4+ error:: TokenError ,
5+ extension:: confidential_transfer:: {
6+ ConfidentialTransferAccount , DecryptableBalance , EncryptedBalance ,
7+ } ,
8+ } ,
49 bytemuck:: { Pod , Zeroable } ,
510 solana_zk_sdk:: {
611 encryption:: {
712 auth_encryption:: { AeCiphertext , AeKey } ,
8- elgamal:: { ElGamalCiphertext , ElGamalKeypair } ,
13+ elgamal:: { ElGamalCiphertext , ElGamalKeypair , ElGamalPubkey } ,
914 pedersen:: PedersenOpening ,
1015 pod:: {
1116 auth_encryption:: PodAeCiphertext ,
1419 } ,
1520 zk_elgamal_proof_program:: proof_data:: CiphertextCiphertextEqualityProofData ,
1621 } ,
22+ spl_token_confidential_transfer_proof_generation:: {
23+ burn:: { burn_split_proof_data, BurnProofData } ,
24+ mint:: { mint_split_proof_data, MintProofData } ,
25+ } ,
1726} ;
1827
1928/// Confidential Mint Burn extension information needed to construct a
@@ -43,7 +52,7 @@ impl SupplyAccountInfo {
4352 /// Computes the current supply from the decryptable supply and the
4453 /// difference between the decryptable supply and the ElGamal encrypted
4554 /// supply ciphertext
46- pub fn decrypt_current_supply (
55+ pub fn decrypted_current_supply (
4756 & self ,
4857 aes_key : & AeKey ,
4958 elgamal_keypair : & ElGamalKeypair ,
@@ -77,12 +86,12 @@ impl SupplyAccountInfo {
7786 /// `RotateSupplyElgamalPubkey` instruction
7887 pub fn generate_rotate_supply_elgamal_pubkey_proof (
7988 & self ,
80- aes_key : & AeKey ,
8189 current_supply_elgamal_keypair : & ElGamalKeypair ,
8290 new_supply_elgamal_keypair : & ElGamalKeypair ,
91+ aes_key : & AeKey ,
8392 ) -> Result < CiphertextCiphertextEqualityProofData , TokenError > {
8493 let current_supply =
85- self . decrypt_current_supply ( aes_key, current_supply_elgamal_keypair) ?;
94+ self . decrypted_current_supply ( aes_key, current_supply_elgamal_keypair) ?;
8695
8796 let new_supply_opening = PedersenOpening :: new_rand ( ) ;
8897 let new_supply_ciphertext = new_supply_elgamal_keypair
@@ -102,4 +111,98 @@ impl SupplyAccountInfo {
102111 )
103112 . map_err ( |_| TokenError :: ProofGeneration )
104113 }
114+
115+ /// Create a mint proof data that is split into equality, ciphertext
116+ /// validity, and range proof.
117+ pub fn generate_split_mint_proof_data (
118+ & self ,
119+ mint_amount : u64 ,
120+ current_supply : u64 ,
121+ supply_elgamal_keypair : & ElGamalKeypair ,
122+ destination_elgamal_pubkey : & ElGamalPubkey ,
123+ auditor_elgamal_pubkey : Option < & ElGamalPubkey > ,
124+ ) -> Result < MintProofData , TokenError > {
125+ let current_supply_ciphertext = self
126+ . current_supply
127+ . try_into ( )
128+ . map_err ( |_| TokenError :: MalformedCiphertext ) ?;
129+
130+ mint_split_proof_data (
131+ & current_supply_ciphertext,
132+ mint_amount,
133+ current_supply,
134+ supply_elgamal_keypair,
135+ destination_elgamal_pubkey,
136+ auditor_elgamal_pubkey,
137+ )
138+ . map_err ( |e| -> TokenError { e. into ( ) } )
139+ }
140+
141+ /// Compute the new decryptable supply.
142+ pub fn new_decryptable_supply (
143+ & self ,
144+ mint_amount : u64 ,
145+ elgamal_keypair : & ElGamalKeypair ,
146+ aes_key : & AeKey ,
147+ ) -> Result < AeCiphertext , TokenError > {
148+ let current_decrypted_supply = self . decrypted_current_supply ( aes_key, elgamal_keypair) ?;
149+ let new_decrypted_available_balance = current_decrypted_supply
150+ . checked_add ( mint_amount)
151+ . ok_or ( TokenError :: Overflow ) ?;
152+
153+ Ok ( aes_key. encrypt ( new_decrypted_available_balance) )
154+ }
155+ }
156+
157+ /// Confidential Mint Burn extension information needed to construct a
158+ /// `Burn` instruction.
159+ #[ repr( C ) ]
160+ #[ derive( Clone , Copy , Debug , Default , PartialEq , Pod , Zeroable ) ]
161+ pub struct BurnAccountInfo {
162+ /// The available balance (encrypted by `encryption_pubkey`)
163+ pub available_balance : EncryptedBalance ,
164+ /// The decryptable available balance
165+ pub decryptable_available_balance : DecryptableBalance ,
166+ }
167+
168+ impl BurnAccountInfo {
169+ /// Create the `ApplyPendingBalance` instruction account information from
170+ /// `ConfidentialTransferAccount`.
171+ pub fn new ( account : & ConfidentialTransferAccount ) -> Self {
172+ Self {
173+ available_balance : account. available_balance ,
174+ decryptable_available_balance : account. decryptable_available_balance ,
175+ }
176+ }
177+
178+ /// Create a burn proof data that is split into equality, ciphertext
179+ /// validity, and range proof.
180+ pub fn generate_split_burn_proof_data (
181+ & self ,
182+ burn_amount : u64 ,
183+ source_elgamal_keypair : & ElGamalKeypair ,
184+ aes_key : & AeKey ,
185+ supply_elgamal_pubkey : & ElGamalPubkey ,
186+ auditor_elgamal_pubkey : Option < & ElGamalPubkey > ,
187+ ) -> Result < BurnProofData , TokenError > {
188+ let current_available_balance_ciphertext = self
189+ . available_balance
190+ . try_into ( )
191+ . map_err ( |_| TokenError :: MalformedCiphertext ) ?;
192+ let current_decryptable_available_balance = self
193+ . decryptable_available_balance
194+ . try_into ( )
195+ . map_err ( |_| TokenError :: MalformedCiphertext ) ?;
196+
197+ burn_split_proof_data (
198+ & current_available_balance_ciphertext,
199+ & current_decryptable_available_balance,
200+ burn_amount,
201+ source_elgamal_keypair,
202+ aes_key,
203+ auditor_elgamal_pubkey,
204+ supply_elgamal_pubkey,
205+ )
206+ . map_err ( |e| -> TokenError { e. into ( ) } )
207+ }
105208}
0 commit comments