Skip to content
This repository has been archived by the owner on Jan 10, 2025. It is now read-only.

Commit

Permalink
[program-2022] Add functions to generate mint/burn proofs from accoun…
Browse files Browse the repository at this point in the history
…t info (#7575)
  • Loading branch information
samkim-crypto authored Dec 11, 2024
1 parent 551931d commit 5380b0e
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 12 deletions.
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() })
}
}

0 comments on commit 5380b0e

Please sign in to comment.