Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

[program-2022] Add functions to generate mint/burn proofs from account info #7575

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions token/confidential-transfer/proof-generation/src/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use {
},
solana_zk_sdk::{
encryption::{
auth_encryption::{AeCiphertext, AeKey},
elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey},
pedersen::Pedersen,
},
Expand All @@ -28,15 +27,13 @@ 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(
current_supply_ciphertext: &ElGamalCiphertext,
mint_amount: u64,
current_supply: u64,
supply_elgamal_keypair: &ElGamalKeypair,
supply_aes_key: &AeKey,
destination_elgamal_pubkey: &ElGamalPubkey,
auditor_elgamal_pubkey: Option<&ElGamalPubkey>,
) -> Result<MintProofData, TokenProofGenerationError> {
Expand Down Expand Up @@ -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),
})
}
3 changes: 0 additions & 3 deletions token/confidential-transfer/proof-tests/tests/proof_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,21 +222,18 @@ 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);

let MintProofData {
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),
)
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<CiphertextCiphertextEqualityProofData, TokenError> {
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
Expand All @@ -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<MintProofData, TokenError> {
let current_supply_ciphertext = self
.current_supply
.try_into()
.map_err(|_| TokenError::MalformedCiphertext)?;

mint_split_proof_data(
&current_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<AeCiphertext, TokenError> {
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<BurnProofData, TokenError> {
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(
&current_available_balance_ciphertext,
&current_decryptable_available_balance,
burn_amount,
source_elgamal_keypair,
aes_key,
auditor_elgamal_pubkey,
supply_elgamal_pubkey,
)
.map_err(|e| -> TokenError { e.into() })
}
}
Loading