1
1
use {
2
2
super :: ConfidentialMintBurn ,
3
- crate :: error:: TokenError ,
3
+ crate :: {
4
+ error:: TokenError ,
5
+ extension:: confidential_transfer:: {
6
+ ConfidentialTransferAccount , DecryptableBalance , EncryptedBalance ,
7
+ } ,
8
+ } ,
4
9
bytemuck:: { Pod , Zeroable } ,
5
10
solana_zk_sdk:: {
6
11
encryption:: {
7
12
auth_encryption:: { AeCiphertext , AeKey } ,
8
- elgamal:: { ElGamalCiphertext , ElGamalKeypair } ,
13
+ elgamal:: { ElGamalCiphertext , ElGamalKeypair , ElGamalPubkey } ,
9
14
pedersen:: PedersenOpening ,
10
15
pod:: {
11
16
auth_encryption:: PodAeCiphertext ,
14
19
} ,
15
20
zk_elgamal_proof_program:: proof_data:: CiphertextCiphertextEqualityProofData ,
16
21
} ,
22
+ spl_token_confidential_transfer_proof_generation:: {
23
+ burn:: { burn_split_proof_data, BurnProofData } ,
24
+ mint:: { mint_split_proof_data, MintProofData } ,
25
+ } ,
17
26
} ;
18
27
19
28
/// Confidential Mint Burn extension information needed to construct a
@@ -43,7 +52,7 @@ impl SupplyAccountInfo {
43
52
/// Computes the current supply from the decryptable supply and the
44
53
/// difference between the decryptable supply and the ElGamal encrypted
45
54
/// supply ciphertext
46
- pub fn decrypt_current_supply (
55
+ pub fn decrypted_current_supply (
47
56
& self ,
48
57
aes_key : & AeKey ,
49
58
elgamal_keypair : & ElGamalKeypair ,
@@ -77,12 +86,12 @@ impl SupplyAccountInfo {
77
86
/// `RotateSupplyElgamalPubkey` instruction
78
87
pub fn generate_rotate_supply_elgamal_pubkey_proof (
79
88
& self ,
80
- aes_key : & AeKey ,
81
89
current_supply_elgamal_keypair : & ElGamalKeypair ,
82
90
new_supply_elgamal_keypair : & ElGamalKeypair ,
91
+ aes_key : & AeKey ,
83
92
) -> Result < CiphertextCiphertextEqualityProofData , TokenError > {
84
93
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) ?;
86
95
87
96
let new_supply_opening = PedersenOpening :: new_rand ( ) ;
88
97
let new_supply_ciphertext = new_supply_elgamal_keypair
@@ -102,4 +111,98 @@ impl SupplyAccountInfo {
102
111
)
103
112
. map_err ( |_| TokenError :: ProofGeneration )
104
113
}
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
+ }
105
208
}
0 commit comments