diff --git a/token/confidential-transfer/proof-generation/src/burn.rs b/token/confidential-transfer/proof-generation/src/burn.rs index ae127d9e9a6..7d7b788fb11 100644 --- a/token/confidential-transfer/proof-generation/src/burn.rs +++ b/token/confidential-transfer/proof-generation/src/burn.rs @@ -36,9 +36,12 @@ pub fn burn_split_proof_data( burn_amount: u64, source_elgamal_keypair: &ElGamalKeypair, source_aes_key: &AeKey, - auditor_elgamal_pubkey: &ElGamalPubkey, + auditor_elgamal_pubkey: Option<&ElGamalPubkey>, supply_elgamal_pubkey: &ElGamalPubkey, ) -> Result { + let default_auditor_pubkey = ElGamalPubkey::default(); + let auditor_elgamal_pubkey = auditor_elgamal_pubkey.unwrap_or(&default_auditor_pubkey); + // split the burn amount into low and high bits let (burn_amount_lo, burn_amount_hi) = try_split_u64(burn_amount, BURN_AMOUNT_LO_BIT_LENGTH) .ok_or(TokenProofGenerationError::IllegalAmountBitLength)?; diff --git a/token/confidential-transfer/proof-generation/src/mint.rs b/token/confidential-transfer/proof-generation/src/mint.rs index 1f06a1c0156..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,10 +34,12 @@ 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: &ElGamalPubkey, + auditor_elgamal_pubkey: Option<&ElGamalPubkey>, ) -> Result { + let default_auditor_pubkey = ElGamalPubkey::default(); + let auditor_elgamal_pubkey = auditor_elgamal_pubkey.unwrap_or(&default_auditor_pubkey); + // split the mint amount into low and high bits let (mint_amount_lo, mint_amount_hi) = try_split_u64(mint_amount, MINT_AMOUNT_LO_BIT_LENGTH) .ok_or(TokenProofGenerationError::IllegalAmountBitLength)?; @@ -158,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 d5e0110e0af..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,15 +229,13 @@ 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, - auditor_pubkey, + Some(auditor_pubkey), ) .unwrap(); @@ -291,7 +288,7 @@ fn test_burn_validity(spendable_balance: u64, burn_amount: u64) { burn_amount, &source_keypair, &aes_key, - auditor_pubkey, + Some(auditor_pubkey), supply_pubkey, ) .unwrap(); 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..62d1946d608 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, @@ -82,7 +91,7 @@ impl SupplyAccountInfo { new_supply_elgamal_keypair: &ElGamalKeypair, ) -> 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, + aes_key: &AeKey, + elgamal_keypair: &ElGamalKeypair, // TODO: check consistency of the order of params + ) -> 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, + auditor_elgamal_pubkey: Option<&ElGamalPubkey>, + supply_elgamal_pubkey: &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() }) + } } diff --git a/token/program-2022/src/extension/confidential_mint_burn/instruction.rs b/token/program-2022/src/extension/confidential_mint_burn/instruction.rs index 6ecd112433d..065e7ff9aeb 100644 --- a/token/program-2022/src/extension/confidential_mint_burn/instruction.rs +++ b/token/program-2022/src/extension/confidential_mint_burn/instruction.rs @@ -26,7 +26,7 @@ use { #[cfg(not(target_os = "solana"))] use { solana_zk_sdk::{ - encryption::{auth_encryption::AeCiphertext, elgamal::ElGamalPubkey}, + encryption::elgamal::ElGamalPubkey, zk_elgamal_proof_program::{ instruction::ProofInstruction, proof_data::{ @@ -291,8 +291,8 @@ pub struct BurnInstructionData { pub fn initialize_mint( token_program_id: &Pubkey, mint: &Pubkey, - supply_elgamal_pubkey: PodElGamalPubkey, - decryptable_supply: PodAeCiphertext, + supply_elgamal_pubkey: &PodElGamalPubkey, + decryptable_supply: &DecryptableBalance, ) -> Result { check_program_account(token_program_id)?; let accounts = vec![AccountMeta::new(*mint, false)]; @@ -303,8 +303,8 @@ pub fn initialize_mint( TokenInstruction::ConfidentialMintBurnExtension, ConfidentialMintBurnInstruction::InitializeMint, &InitializeMintData { - supply_elgamal_pubkey, - decryptable_supply, + supply_elgamal_pubkey: *supply_elgamal_pubkey, + decryptable_supply: *decryptable_supply, }, )) } @@ -317,7 +317,7 @@ pub fn rotate_supply_elgamal_pubkey( mint: &Pubkey, authority: &Pubkey, multisig_signers: &[&Pubkey], - new_supply_elgamal_pubkey: ElGamalPubkey, + new_supply_elgamal_pubkey: &PodElGamalPubkey, ciphertext_equality_proof: ProofLocation, ) -> Result, ProgramError> { check_program_account(token_program_id)?; @@ -349,7 +349,7 @@ pub fn rotate_supply_elgamal_pubkey( TokenInstruction::ConfidentialMintBurnExtension, ConfidentialMintBurnInstruction::RotateSupplyElGamalPubkey, &RotateSupplyElGamalPubkeyData { - new_supply_elgamal_pubkey: PodElGamalPubkey::from(new_supply_elgamal_pubkey), + new_supply_elgamal_pubkey: *new_supply_elgamal_pubkey, proof_instruction_offset, }, )]; @@ -366,7 +366,7 @@ pub fn update_decryptable_supply( mint: &Pubkey, authority: &Pubkey, multisig_signers: &[&Pubkey], - new_decryptable_supply: AeCiphertext, + new_decryptable_supply: &DecryptableBalance, ) -> Result { check_program_account(token_program_id)?; let mut accounts = vec![ @@ -382,7 +382,7 @@ pub fn update_decryptable_supply( TokenInstruction::ConfidentialMintBurnExtension, ConfidentialMintBurnInstruction::UpdateDecryptableSupply, &UpdateDecryptableSupplyData { - new_decryptable_supply: new_decryptable_supply.into(), + new_decryptable_supply: *new_decryptable_supply, }, )) } @@ -417,7 +417,7 @@ pub fn confidential_mint_with_split_proofs( BatchedGroupedCiphertext3HandlesValidityProofData, >, range_proof_location: ProofLocation, - new_decryptable_supply: AeCiphertext, + new_decryptable_supply: &DecryptableBalance, ) -> Result, ProgramError> { check_program_account(token_program_id)?; let mut accounts = vec![AccountMeta::new(*token_account, false)]; @@ -473,7 +473,7 @@ pub fn confidential_mint_with_split_proofs( TokenInstruction::ConfidentialMintBurnExtension, ConfidentialMintBurnInstruction::Mint, &MintInstructionData { - new_decryptable_supply: new_decryptable_supply.into(), + new_decryptable_supply: *new_decryptable_supply, mint_amount_auditor_ciphertext_lo: *mint_amount_auditor_ciphertext_lo, mint_amount_auditor_ciphertext_hi: *mint_amount_auditor_ciphertext_hi, equality_proof_instruction_offset, @@ -495,7 +495,7 @@ pub fn confidential_burn_with_split_proofs( token_account: &Pubkey, mint: &Pubkey, supply_elgamal_pubkey: Option, - new_decryptable_available_balance: DecryptableBalance, + new_decryptable_available_balance: &DecryptableBalance, burn_amount_auditor_ciphertext_lo: &PodElGamalCiphertext, burn_amount_auditor_ciphertext_hi: &PodElGamalCiphertext, authority: &Pubkey, @@ -559,7 +559,7 @@ pub fn confidential_burn_with_split_proofs( TokenInstruction::ConfidentialMintBurnExtension, ConfidentialMintBurnInstruction::Burn, &BurnInstructionData { - new_decryptable_available_balance, + new_decryptable_available_balance: *new_decryptable_available_balance, burn_amount_auditor_ciphertext_lo: *burn_amount_auditor_ciphertext_lo, burn_amount_auditor_ciphertext_hi: *burn_amount_auditor_ciphertext_hi, equality_proof_instruction_offset, diff --git a/token/program-2022/src/extension/confidential_transfer/account_info.rs b/token/program-2022/src/extension/confidential_transfer/account_info.rs index 39b819b9a70..672a8028904 100644 --- a/token/program-2022/src/extension/confidential_transfer/account_info.rs +++ b/token/program-2022/src/extension/confidential_transfer/account_info.rs @@ -147,7 +147,7 @@ impl ApplyPendingBalanceAccountInfo { #[repr(C)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct WithdrawAccountInfo { - /// The available balance (encrypted by `encrypiton_pubkey`) + /// The available balance (encrypted by `encryption_pubkey`) pub available_balance: EncryptedBalance, /// The decryptable available balance pub decryptable_available_balance: DecryptableBalance, @@ -214,7 +214,7 @@ impl WithdrawAccountInfo { #[repr(C)] #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] pub struct TransferAccountInfo { - /// The available balance (encrypted by `encrypiton_pubkey`) + /// The available balance (encrypted by `encryption_pubkey`) pub available_balance: EncryptedBalance, /// The decryptable available balance pub decryptable_available_balance: DecryptableBalance, diff --git a/token/program-2022/src/extension/confidential_transfer/instruction.rs b/token/program-2022/src/extension/confidential_transfer/instruction.rs index 1419f08e38f..548eabeca17 100644 --- a/token/program-2022/src/extension/confidential_transfer/instruction.rs +++ b/token/program-2022/src/extension/confidential_transfer/instruction.rs @@ -760,7 +760,7 @@ pub fn inner_configure_account( token_program_id: &Pubkey, token_account: &Pubkey, mint: &Pubkey, - decryptable_zero_balance: PodAeCiphertext, + decryptable_zero_balance: &DecryptableBalance, maximum_pending_balance_credit_counter: u64, authority: &Pubkey, multisig_signers: &[&Pubkey], @@ -802,7 +802,7 @@ pub fn inner_configure_account( TokenInstruction::ConfidentialTransferExtension, ConfidentialTransferInstruction::ConfigureAccount, &ConfigureAccountInstructionData { - decryptable_zero_balance, + decryptable_zero_balance: *decryptable_zero_balance, maximum_pending_balance_credit_counter: maximum_pending_balance_credit_counter.into(), proof_instruction_offset, }, @@ -815,7 +815,7 @@ pub fn configure_account( token_program_id: &Pubkey, token_account: &Pubkey, mint: &Pubkey, - decryptable_zero_balance: PodAeCiphertext, + decryptable_zero_balance: &DecryptableBalance, maximum_pending_balance_credit_counter: u64, authority: &Pubkey, multisig_signers: &[&Pubkey], @@ -1013,7 +1013,7 @@ pub fn inner_withdraw( mint: &Pubkey, amount: u64, decimals: u8, - new_decryptable_available_balance: DecryptableBalance, + new_decryptable_available_balance: &DecryptableBalance, authority: &Pubkey, multisig_signers: &[&Pubkey], equality_proof_data_location: ProofLocation, @@ -1076,7 +1076,7 @@ pub fn inner_withdraw( &WithdrawInstructionData { amount: amount.into(), decimals, - new_decryptable_available_balance, + new_decryptable_available_balance: *new_decryptable_available_balance, equality_proof_instruction_offset, range_proof_instruction_offset, }, @@ -1091,7 +1091,7 @@ pub fn withdraw( mint: &Pubkey, amount: u64, decimals: u8, - new_decryptable_available_balance: PodAeCiphertext, + new_decryptable_available_balance: &DecryptableBalance, authority: &Pubkey, multisig_signers: &[&Pubkey], equality_proof_data_location: ProofLocation, @@ -1162,7 +1162,7 @@ pub fn inner_transfer( source_token_account: &Pubkey, mint: &Pubkey, destination_token_account: &Pubkey, - new_source_decryptable_available_balance: DecryptableBalance, + new_source_decryptable_available_balance: &DecryptableBalance, transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext, transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext, authority: &Pubkey, @@ -1244,7 +1244,7 @@ pub fn inner_transfer( TokenInstruction::ConfidentialTransferExtension, ConfidentialTransferInstruction::Transfer, &TransferInstructionData { - new_source_decryptable_available_balance, + new_source_decryptable_available_balance: *new_source_decryptable_available_balance, transfer_amount_auditor_ciphertext_lo: *transfer_amount_auditor_ciphertext_lo, transfer_amount_auditor_ciphertext_hi: *transfer_amount_auditor_ciphertext_hi, equality_proof_instruction_offset, @@ -1261,7 +1261,7 @@ pub fn transfer( source_token_account: &Pubkey, mint: &Pubkey, destination_token_account: &Pubkey, - new_source_decryptable_available_balance: DecryptableBalance, + new_source_decryptable_available_balance: &DecryptableBalance, transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext, transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext, authority: &Pubkey, @@ -1359,7 +1359,7 @@ pub fn inner_apply_pending_balance( token_program_id: &Pubkey, token_account: &Pubkey, expected_pending_balance_credit_counter: u64, - new_decryptable_available_balance: DecryptableBalance, + new_decryptable_available_balance: &DecryptableBalance, authority: &Pubkey, multisig_signers: &[&Pubkey], ) -> Result { @@ -1380,7 +1380,7 @@ pub fn inner_apply_pending_balance( ConfidentialTransferInstruction::ApplyPendingBalance, &ApplyPendingBalanceData { expected_pending_balance_credit_counter: expected_pending_balance_credit_counter.into(), - new_decryptable_available_balance, + new_decryptable_available_balance: *new_decryptable_available_balance, }, )) } @@ -1390,7 +1390,7 @@ pub fn apply_pending_balance( token_program_id: &Pubkey, token_account: &Pubkey, pending_balance_instructions: u64, - new_decryptable_available_balance: PodAeCiphertext, + new_decryptable_available_balance: &DecryptableBalance, authority: &Pubkey, multisig_signers: &[&Pubkey], ) -> Result { @@ -1503,7 +1503,7 @@ pub fn inner_transfer_with_fee( source_token_account: &Pubkey, mint: &Pubkey, destination_token_account: &Pubkey, - new_source_decryptable_available_balance: DecryptableBalance, + new_source_decryptable_available_balance: &DecryptableBalance, transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext, transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext, authority: &Pubkey, @@ -1618,7 +1618,7 @@ pub fn inner_transfer_with_fee( TokenInstruction::ConfidentialTransferExtension, ConfidentialTransferInstruction::TransferWithFee, &TransferWithFeeInstructionData { - new_source_decryptable_available_balance, + new_source_decryptable_available_balance: *new_source_decryptable_available_balance, transfer_amount_auditor_ciphertext_lo: *transfer_amount_auditor_ciphertext_lo, transfer_amount_auditor_ciphertext_hi: *transfer_amount_auditor_ciphertext_hi, equality_proof_instruction_offset, @@ -1637,7 +1637,7 @@ pub fn transfer_with_fee( source_token_account: &Pubkey, mint: &Pubkey, destination_token_account: &Pubkey, - new_source_decryptable_available_balance: DecryptableBalance, + new_source_decryptable_available_balance: &DecryptableBalance, transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext, transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext, authority: &Pubkey, diff --git a/token/program-2022/src/extension/confidential_transfer/mod.rs b/token/program-2022/src/extension/confidential_transfer/mod.rs index ab1bb71e162..baa371cf89f 100644 --- a/token/program-2022/src/extension/confidential_transfer/mod.rs +++ b/token/program-2022/src/extension/confidential_transfer/mod.rs @@ -90,7 +90,7 @@ pub struct ConfidentialTransferAccount { /// The high 48 bits of the pending balance (encrypted by `elgamal_pubkey`) pub pending_balance_hi: EncryptedBalance, - /// The available balance (encrypted by `encrypiton_pubkey`) + /// The available balance (encrypted by `encryption_pubkey`) pub available_balance: EncryptedBalance, /// The decryptable available balance diff --git a/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs b/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs index b27c82acb61..1d140e5af01 100644 --- a/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs +++ b/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs @@ -275,7 +275,7 @@ pub fn initialize_confidential_transfer_fee_config( token_program_id: &Pubkey, mint: &Pubkey, authority: Option, - withdraw_withheld_authority_elgamal_pubkey: PodElGamalPubkey, + withdraw_withheld_authority_elgamal_pubkey: &PodElGamalPubkey, ) -> Result { check_program_account(token_program_id)?; let accounts = vec![AccountMeta::new(*mint, false)]; @@ -287,7 +287,7 @@ pub fn initialize_confidential_transfer_fee_config( ConfidentialTransferFeeInstruction::InitializeConfidentialTransferFeeConfig, &InitializeConfidentialTransferFeeConfigData { authority: authority.try_into()?, - withdraw_withheld_authority_elgamal_pubkey, + withdraw_withheld_authority_elgamal_pubkey: *withdraw_withheld_authority_elgamal_pubkey, }, )) }