Skip to content

Commit

Permalink
add auditor ciphertext to confidential mint and burn instruction data
Browse files Browse the repository at this point in the history
  • Loading branch information
samkim-crypto committed Nov 11, 2024
1 parent 8e7bffb commit e908b0d
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ use {
program_error::ProgramError,
pubkey::Pubkey,
},
solana_zk_sdk::encryption::pod::{auth_encryption::PodAeCiphertext, elgamal::PodElGamalPubkey},
solana_zk_sdk::encryption::pod::{
auth_encryption::PodAeCiphertext,
elgamal::{PodElGamalCiphertext, PodElGamalPubkey},
},
};
#[cfg(not(target_os = "solana"))]
use {
Expand Down Expand Up @@ -229,6 +232,12 @@ pub struct MintInstructionData {
/// The new decryptable supply if the mint succeeds
#[cfg_attr(feature = "serde-traits", serde(with = "aeciphertext_fromstr"))]
pub new_decryptable_supply: PodAeCiphertext,
/// The transfer amount encrypted under the auditor ElGamal public key
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
pub mint_amount_auditor_ciphertext_lo: PodElGamalCiphertext,
/// The transfer amount encrypted under the auditor ElGamal public key
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
pub mint_amount_auditor_ciphertext_hi: PodElGamalCiphertext,
/// Relative location of the
/// `ProofInstruction::VerifyCiphertextCommitmentEquality` instruction
/// to the `ConfidentialMint` instruction in the transaction. 0 if the
Expand All @@ -254,6 +263,12 @@ pub struct BurnInstructionData {
/// The new decryptable balance of the burner if the burn succeeds
#[cfg_attr(feature = "serde-traits", serde(with = "aeciphertext_fromstr"))]
pub new_decryptable_available_balance: DecryptableBalance,
/// The transfer amount encrypted under the auditor ElGamal public key
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
pub burn_amount_auditor_ciphertext_lo: PodElGamalCiphertext,
/// The transfer amount encrypted under the auditor ElGamal public key
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
pub burn_amount_auditor_ciphertext_hi: PodElGamalCiphertext,
/// Relative location of the
/// `ProofInstruction::VerifyCiphertextCommitmentEquality` instruction
/// to the `ConfidentialMint` instruction in the transaction. 0 if the
Expand Down Expand Up @@ -391,6 +406,8 @@ pub fn confidential_mint_with_split_proofs(
token_account: &Pubkey,
mint: &Pubkey,
supply_elgamal_pubkey: Option<ElGamalPubkey>,
mint_amount_auditor_ciphertext_lo: &PodElGamalCiphertext,
mint_amount_auditor_ciphertext_hi: &PodElGamalCiphertext,
authority: &Pubkey,
multisig_signers: &[&Pubkey],
equality_proof_location: ProofLocation<CiphertextCommitmentEqualityProofData>,
Expand Down Expand Up @@ -455,6 +472,8 @@ pub fn confidential_mint_with_split_proofs(
ConfidentialMintBurnInstruction::Mint,
&MintInstructionData {
new_decryptable_supply: new_decryptable_supply.into(),
mint_amount_auditor_ciphertext_lo: *mint_amount_auditor_ciphertext_lo,
mint_amount_auditor_ciphertext_hi: *mint_amount_auditor_ciphertext_hi,
equality_proof_instruction_offset,
ciphertext_validity_proof_instruction_offset,
range_proof_instruction_offset,
Expand All @@ -475,6 +494,8 @@ pub fn confidential_burn_with_split_proofs(
mint: &Pubkey,
supply_elgamal_pubkey: Option<ElGamalPubkey>,
new_decryptable_available_balance: DecryptableBalance,
burn_amount_auditor_ciphertext_lo: &PodElGamalCiphertext,
burn_amount_auditor_ciphertext_hi: &PodElGamalCiphertext,
authority: &Pubkey,
multisig_signers: &[&Pubkey],
equality_proof_location: ProofLocation<CiphertextCommitmentEqualityProofData>,
Expand Down Expand Up @@ -537,6 +558,8 @@ pub fn confidential_burn_with_split_proofs(
ConfidentialMintBurnInstruction::Burn,
&BurnInstructionData {
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,
ciphertext_validity_proof_instruction_offset,
range_proof_instruction_offset,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use spl_token_confidential_transfer_ciphertext_arithmetic as ciphertext_arithmetic;
use {
crate::{
check_program_account,
check_auditor_ciphertext, check_program_account,
error::TokenError,
extension::{
confidential_mint_burn::{
Expand Down Expand Up @@ -210,20 +210,36 @@ fn process_confidential_mint(
}
}

let proof_context_auditor_ciphertext_lo = proof_context
.mint_amount_ciphertext_lo
.try_extract_ciphertext(2)
.map_err(|e| -> TokenError { e.into() })?;
let proof_context_auditor_ciphertext_hi = proof_context
.mint_amount_ciphertext_hi
.try_extract_ciphertext(2)
.map_err(|e| -> TokenError { e.into() })?;

check_auditor_ciphertext(
&data.mint_amount_auditor_ciphertext_lo,
&data.mint_amount_auditor_ciphertext_hi,
&proof_context_auditor_ciphertext_lo,
&proof_context_auditor_ciphertext_hi,
)?;

confidential_transfer_account.pending_balance_lo = ciphertext_arithmetic::add(
&confidential_transfer_account.pending_balance_lo,
&proof_context
.mint_amount_ciphertext_lo
.try_extract_ciphertext(0)
.map_err(|_| ProgramError::InvalidAccountData)?,
.map_err(|e| -> TokenError { e.into() })?,
)
.ok_or(TokenError::CiphertextArithmeticFailed)?;
confidential_transfer_account.pending_balance_hi = ciphertext_arithmetic::add(
&confidential_transfer_account.pending_balance_hi,
&proof_context
.mint_amount_ciphertext_hi
.try_extract_ciphertext(0)
.map_err(|_| ProgramError::InvalidAccountData)?,
.map_err(|e| -> TokenError { e.into() })?,
)
.ok_or(TokenError::CiphertextArithmeticFailed)?;

Expand Down Expand Up @@ -311,14 +327,30 @@ fn process_confidential_burn(
return Err(TokenError::ConfidentialTransferElGamalPubkeyMismatch.into());
}

let proof_context_auditor_ciphertext_lo = proof_context
.burn_amount_ciphertext_lo
.try_extract_ciphertext(2)
.map_err(|e| -> TokenError { e.into() })?;
let proof_context_auditor_ciphertext_hi = proof_context
.burn_amount_ciphertext_hi
.try_extract_ciphertext(2)
.map_err(|e| -> TokenError { e.into() })?;

check_auditor_ciphertext(
&data.burn_amount_auditor_ciphertext_lo,
&data.burn_amount_auditor_ciphertext_hi,
&proof_context_auditor_ciphertext_lo,
&proof_context_auditor_ciphertext_hi,
)?;

let burn_amount_lo = &proof_context
.burn_amount_ciphertext_lo
.try_extract_ciphertext(0)
.map_err(|_| ProgramError::InvalidAccountData)?;
.map_err(|e| -> TokenError { e.into() })?;
let burn_amount_hi = &proof_context
.burn_amount_ciphertext_hi
.try_extract_ciphertext(0)
.map_err(|_| ProgramError::InvalidAccountData)?;
.map_err(|e| -> TokenError { e.into() })?;

let new_source_available_balance = ciphertext_arithmetic::subtract_with_lo_hi(
&confidential_transfer_account.available_balance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use {
};
use {
crate::{
check_elgamal_registry_program_account, check_program_account,
check_auditor_ciphertext, check_elgamal_registry_program_account, check_program_account,
error::TokenError,
extension::{
confidential_transfer::{instruction::*, verify_proof::*, *},
Expand Down Expand Up @@ -801,23 +801,6 @@ fn process_transfer(
Ok(())
}

/// Check instruction data and proof data auditor ciphertext consistency
#[cfg(feature = "zk-ops")]
fn check_auditor_ciphertext(
instruction_data_auditor_ciphertext_lo: &PodElGamalCiphertext,
instruction_data_auditor_ciphertext_hi: &PodElGamalCiphertext,
proof_context_auditor_ciphertext_lo: &PodElGamalCiphertext,
proof_context_auditor_ciphertext_hi: &PodElGamalCiphertext,
) -> ProgramResult {
if instruction_data_auditor_ciphertext_lo != proof_context_auditor_ciphertext_lo {
return Err(TokenError::ConfidentialTransferBalanceMismatch.into());
}
if instruction_data_auditor_ciphertext_hi != proof_context_auditor_ciphertext_hi {
return Err(TokenError::ConfidentialTransferBalanceMismatch.into());
}
Ok(())
}

/// Processes the changes for the sending party of a confidential transfer
#[cfg(feature = "zk-ops")]
fn process_source_for_transfer(
Expand Down
25 changes: 23 additions & 2 deletions token/program-2022/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ mod entrypoint;

// Export current sdk types for downstream users building with a different sdk
// version
use solana_program::{
entrypoint::ProgramResult, program_error::ProgramError, pubkey::Pubkey, system_program,
use {
error::TokenError,
solana_program::{
entrypoint::ProgramResult, program_error::ProgramError, pubkey::Pubkey, system_program,
},
solana_zk_sdk::encryption::pod::elgamal::PodElGamalCiphertext,
};
pub use {solana_program, solana_zk_sdk};

Expand Down Expand Up @@ -139,3 +143,20 @@ pub(crate) fn check_elgamal_registry_program_account(
}
Ok(())
}

/// Check instruction data and proof data auditor ciphertext consistency
#[cfg(feature = "zk-ops")]
pub(crate) fn check_auditor_ciphertext(
instruction_data_auditor_ciphertext_lo: &PodElGamalCiphertext,
instruction_data_auditor_ciphertext_hi: &PodElGamalCiphertext,
proof_context_auditor_ciphertext_lo: &PodElGamalCiphertext,
proof_context_auditor_ciphertext_hi: &PodElGamalCiphertext,
) -> ProgramResult {
if instruction_data_auditor_ciphertext_lo != proof_context_auditor_ciphertext_lo {
return Err(TokenError::ConfidentialTransferBalanceMismatch.into());
}
if instruction_data_auditor_ciphertext_hi != proof_context_auditor_ciphertext_hi {
return Err(TokenError::ConfidentialTransferBalanceMismatch.into());
}
Ok(())
}

0 comments on commit e908b0d

Please sign in to comment.