diff --git a/token/confidential-transfer/proof-generation/src/mint.rs b/token/confidential-transfer/proof-generation/src/mint.rs index a670a26ee27..8e03e6d6c1a 100644 --- a/token/confidential-transfer/proof-generation/src/mint.rs +++ b/token/confidential-transfer/proof-generation/src/mint.rs @@ -5,7 +5,6 @@ use { }, solana_zk_sdk::{ encryption::{ - auth_encryption::{AeCiphertext, AeKey}, elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey}, pedersen::Pedersen, }, @@ -28,7 +27,6 @@ pub struct MintProofData { pub ciphertext_validity_proof_data_with_ciphertext: CiphertextValidityProofWithAuditorCiphertext, pub range_proof_data: BatchedRangeProofU128Data, - pub new_decryptable_supply: AeCiphertext, } pub fn mint_split_proof_data( @@ -36,7 +34,6 @@ pub fn mint_split_proof_data( mint_amount: u64, current_supply: u64, supply_elgamal_keypair: &ElGamalKeypair, - supply_aes_key: &AeKey, destination_elgamal_pubkey: &ElGamalPubkey, auditor_elgamal_pubkey: Option<&ElGamalPubkey>, ) -> Result { @@ -161,6 +158,5 @@ pub fn mint_split_proof_data( equality_proof_data, ciphertext_validity_proof_data_with_ciphertext, range_proof_data, - new_decryptable_supply: supply_aes_key.encrypt(new_supply), }) } diff --git a/token/confidential-transfer/proof-tests/tests/proof_test.rs b/token/confidential-transfer/proof-tests/tests/proof_test.rs index 9bcbfa25951..b9444cd40e4 100644 --- a/token/confidential-transfer/proof-tests/tests/proof_test.rs +++ b/token/confidential-transfer/proof-tests/tests/proof_test.rs @@ -222,7 +222,6 @@ fn test_mint_validity(mint_amount: u64, supply: u64) { let auditor_pubkey = auditor_keypair.pubkey(); let supply_keypair = ElGamalKeypair::new_rand(); - let supply_aes_key = AeKey::new_rand(); let supply_ciphertext = supply_keypair.pubkey().encrypt(supply); @@ -230,13 +229,11 @@ fn test_mint_validity(mint_amount: u64, supply: u64) { equality_proof_data, ciphertext_validity_proof_data_with_ciphertext, range_proof_data, - new_decryptable_supply: _, } = mint_split_proof_data( &supply_ciphertext, mint_amount, supply, &supply_keypair, - &supply_aes_key, destination_pubkey, Some(auditor_pubkey), ) diff --git a/token/program-2022/src/extension/confidential_mint_burn/account_info.rs b/token/program-2022/src/extension/confidential_mint_burn/account_info.rs index 772355af016..53f678d1082 100644 --- a/token/program-2022/src/extension/confidential_mint_burn/account_info.rs +++ b/token/program-2022/src/extension/confidential_mint_burn/account_info.rs @@ -1,11 +1,16 @@ use { super::ConfidentialMintBurn, - crate::error::TokenError, + crate::{ + error::TokenError, + extension::confidential_transfer::{ + ConfidentialTransferAccount, DecryptableBalance, EncryptedBalance, + }, + }, bytemuck::{Pod, Zeroable}, solana_zk_sdk::{ encryption::{ auth_encryption::{AeCiphertext, AeKey}, - elgamal::{ElGamalCiphertext, ElGamalKeypair}, + elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey}, pedersen::PedersenOpening, pod::{ auth_encryption::PodAeCiphertext, @@ -14,6 +19,10 @@ use { }, zk_elgamal_proof_program::proof_data::CiphertextCiphertextEqualityProofData, }, + spl_token_confidential_transfer_proof_generation::{ + burn::{burn_split_proof_data, BurnProofData}, + mint::{mint_split_proof_data, MintProofData}, + }, }; /// Confidential Mint Burn extension information needed to construct a @@ -43,7 +52,7 @@ impl SupplyAccountInfo { /// Computes the current supply from the decryptable supply and the /// difference between the decryptable supply and the ElGamal encrypted /// supply ciphertext - pub fn decrypt_current_supply( + pub fn decrypted_current_supply( &self, aes_key: &AeKey, elgamal_keypair: &ElGamalKeypair, @@ -77,12 +86,12 @@ impl SupplyAccountInfo { /// `RotateSupplyElgamalPubkey` instruction pub fn generate_rotate_supply_elgamal_pubkey_proof( &self, - aes_key: &AeKey, current_supply_elgamal_keypair: &ElGamalKeypair, new_supply_elgamal_keypair: &ElGamalKeypair, + aes_key: &AeKey, ) -> Result { let current_supply = - self.decrypt_current_supply(aes_key, current_supply_elgamal_keypair)?; + self.decrypted_current_supply(aes_key, current_supply_elgamal_keypair)?; let new_supply_opening = PedersenOpening::new_rand(); let new_supply_ciphertext = new_supply_elgamal_keypair @@ -102,4 +111,98 @@ impl SupplyAccountInfo { ) .map_err(|_| TokenError::ProofGeneration) } + + /// Create a mint proof data that is split into equality, ciphertext + /// validity, and range proof. + pub fn generate_split_mint_proof_data( + &self, + mint_amount: u64, + current_supply: u64, + supply_elgamal_keypair: &ElGamalKeypair, + destination_elgamal_pubkey: &ElGamalPubkey, + auditor_elgamal_pubkey: Option<&ElGamalPubkey>, + ) -> Result { + let current_supply_ciphertext = self + .current_supply + .try_into() + .map_err(|_| TokenError::MalformedCiphertext)?; + + mint_split_proof_data( + ¤t_supply_ciphertext, + mint_amount, + current_supply, + supply_elgamal_keypair, + destination_elgamal_pubkey, + auditor_elgamal_pubkey, + ) + .map_err(|e| -> TokenError { e.into() }) + } + + /// Compute the new decryptable supply. + pub fn new_decryptable_supply( + &self, + mint_amount: u64, + elgamal_keypair: &ElGamalKeypair, + aes_key: &AeKey, + ) -> Result { + let current_decrypted_supply = self.decrypted_current_supply(aes_key, elgamal_keypair)?; + let new_decrypted_available_balance = current_decrypted_supply + .checked_add(mint_amount) + .ok_or(TokenError::Overflow)?; + + Ok(aes_key.encrypt(new_decrypted_available_balance)) + } +} + +/// Confidential Mint Burn extension information needed to construct a +/// `Burn` instruction. +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] +pub struct BurnAccountInfo { + /// The available balance (encrypted by `encryption_pubkey`) + pub available_balance: EncryptedBalance, + /// The decryptable available balance + pub decryptable_available_balance: DecryptableBalance, +} + +impl BurnAccountInfo { + /// Create the `ApplyPendingBalance` instruction account information from + /// `ConfidentialTransferAccount`. + pub fn new(account: &ConfidentialTransferAccount) -> Self { + Self { + available_balance: account.available_balance, + decryptable_available_balance: account.decryptable_available_balance, + } + } + + /// Create a burn proof data that is split into equality, ciphertext + /// validity, and range proof. + pub fn generate_split_burn_proof_data( + &self, + burn_amount: u64, + source_elgamal_keypair: &ElGamalKeypair, + aes_key: &AeKey, + supply_elgamal_pubkey: &ElGamalPubkey, + auditor_elgamal_pubkey: Option<&ElGamalPubkey>, + ) -> Result { + let current_available_balance_ciphertext = self + .available_balance + .try_into() + .map_err(|_| TokenError::MalformedCiphertext)?; + let current_decryptable_available_balance = self + .decryptable_available_balance + .try_into() + .map_err(|_| TokenError::MalformedCiphertext)?; + + burn_split_proof_data( + ¤t_available_balance_ciphertext, + ¤t_decryptable_available_balance, + burn_amount, + source_elgamal_keypair, + aes_key, + auditor_elgamal_pubkey, + supply_elgamal_pubkey, + ) + .map_err(|e| -> TokenError { e.into() }) + } }