Skip to content

Commit

Permalink
[program-2022] Add auditor ciphertexts to instruction data (#7480)
Browse files Browse the repository at this point in the history
* add auditor ciphertext to transfer instruction data

* add auditor ciphertext to confidential mint and burn instruction data

* cargo fmt

* cargo clippy

* import `elgamalciphertext_fromstr`

* update token-cli

* use `map_err(TokenError::from)`

* add `CiphertextValidityProofWithCiphertext` type

* update token-cli using the updated syntax

* add comments describing the type `CiphertextValidityProofWithCiphertext`

* update proof tests

* update to `CiphertextValidityProofWithAuditorCiphertext`
  • Loading branch information
samkim-crypto authored Nov 15, 2024
1 parent 115e594 commit 45b214f
Show file tree
Hide file tree
Showing 17 changed files with 558 additions and 134 deletions.
22 changes: 18 additions & 4 deletions token/cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ use {
},
spl_token_client::{
client::{ProgramRpcClientSendTransaction, RpcClientResponse},
token::{ComputeUnitLimit, ExtensionInitializationParams, ProofAccount, Token},
token::{
ComputeUnitLimit, ExtensionInitializationParams, ProofAccount,
ProofAccountWithCiphertext, Token,
},
},
spl_token_confidential_transfer_proof_generation::{
transfer::TransferProofData, withdraw::WithdrawProofData,
Expand Down Expand Up @@ -1611,7 +1614,7 @@ async fn command_transfer(

let TransferProofData {
equality_proof_data,
ciphertext_validity_proof_data,
ciphertext_validity_proof_data_with_ciphertext,
range_proof_data,
} = transfer_account_info
.generate_split_transfer_proof_data(
Expand All @@ -1623,6 +1626,11 @@ async fn command_transfer(
)
.unwrap();

let transfer_amount_auditor_ciphertext_lo =
ciphertext_validity_proof_data_with_ciphertext.ciphertext_lo;
let transfer_amount_auditor_ciphertext_hi =
ciphertext_validity_proof_data_with_ciphertext.ciphertext_hi;

// setup proofs
let create_range_proof_context_signer = &[&range_proof_context_state_account];
let create_equality_proof_context_signer = &[&equality_proof_context_state_account];
Expand All @@ -1647,7 +1655,7 @@ async fn command_transfer(
token.confidential_transfer_create_context_state_account(
&ciphertext_validity_proof_pubkey,
&context_state_authority_pubkey,
&ciphertext_validity_proof_data,
&ciphertext_validity_proof_data_with_ciphertext.proof_data,
false,
create_ciphertext_validity_proof_context_signer
)
Expand All @@ -1661,13 +1669,19 @@ async fn command_transfer(
let range_proof_context_proof_account =
ProofAccount::ContextAccount(range_proof_pubkey);

let ciphertext_validity_proof_account_with_ciphertext = ProofAccountWithCiphertext {
proof_account: ciphertext_validity_proof_context_proof_account,
ciphertext_lo: transfer_amount_auditor_ciphertext_lo,
ciphertext_hi: transfer_amount_auditor_ciphertext_hi,
};

let transfer_result = token
.confidential_transfer_transfer(
&sender,
&recipient_token_account,
&sender_owner,
Some(&equality_proof_context_proof_account),
Some(&ciphertext_validity_proof_context_proof_account),
Some(&ciphertext_validity_proof_account_with_ciphertext),
Some(&range_proof_context_proof_account),
transfer_balance,
Some(transfer_account_info),
Expand Down
171 changes: 113 additions & 58 deletions token/client/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use {
encryption::{
auth_encryption::AeKey,
elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey, ElGamalSecretKey},
pod::elgamal::PodElGamalPubkey,
pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey},
},
zk_elgamal_proof_program::{
self,
Expand Down Expand Up @@ -348,6 +348,12 @@ pub enum ProofAccount {
RecordAccount(Pubkey, u32),
}

pub struct ProofAccountWithCiphertext {
pub proof_account: ProofAccount,
pub ciphertext_lo: PodElGamalCiphertext,
pub ciphertext_hi: PodElGamalCiphertext,
}

pub struct Token<T> {
client: Arc<dyn ProgramClient<T>>,
pubkey: Pubkey, /* token mint */
Expand Down Expand Up @@ -2198,7 +2204,7 @@ where
destination_account: &Pubkey,
source_authority: &Pubkey,
equality_proof_account: Option<&ProofAccount>,
ciphertext_validity_proof_account: Option<&ProofAccount>,
ciphertext_validity_proof_account_with_ciphertext: Option<&ProofAccountWithCiphertext>,
range_proof_account: Option<&ProofAccount>,
transfer_amount: u64,
account_info: Option<TransferAccountInfo>,
Expand All @@ -2220,46 +2226,65 @@ where
TransferAccountInfo::new(confidential_transfer_account)
};

let (equality_proof_data, ciphertext_validity_proof_data, range_proof_data) = if [
equality_proof_account,
ciphertext_validity_proof_account,
range_proof_account,
]
.iter()
.all(|proof_account| proof_account.is_some())
{
(None, None, None)
} else {
let TransferProofData {
equality_proof_data,
ciphertext_validity_proof_data,
range_proof_data,
} = account_info
.generate_split_transfer_proof_data(
transfer_amount,
source_elgamal_keypair,
source_aes_key,
destination_elgamal_pubkey,
auditor_elgamal_pubkey,
)
.map_err(|_| TokenError::ProofGeneration)?;
let (equality_proof_data, ciphertext_validity_proof_data_with_ciphertext, range_proof_data) =
if equality_proof_account.is_some()
&& ciphertext_validity_proof_account_with_ciphertext.is_some()
&& range_proof_account.is_some()
{
(None, None, None)
} else {
let TransferProofData {
equality_proof_data,
ciphertext_validity_proof_data_with_ciphertext,
range_proof_data,
} = account_info
.generate_split_transfer_proof_data(
transfer_amount,
source_elgamal_keypair,
source_aes_key,
destination_elgamal_pubkey,
auditor_elgamal_pubkey,
)
.map_err(|_| TokenError::ProofGeneration)?;

// if proof accounts are none, then proof data must be included as instruction
// data
let equality_proof_data = equality_proof_account
.is_none()
.then_some(equality_proof_data);
let ciphertext_validity_proof_data = ciphertext_validity_proof_account
.is_none()
.then_some(ciphertext_validity_proof_data);
let range_proof_data = range_proof_account.is_none().then_some(range_proof_data);
// if proof accounts are none, then proof data must be included as instruction
// data
let equality_proof_data = equality_proof_account
.is_none()
.then_some(equality_proof_data);
let ciphertext_validity_proof_data_with_ciphertext =
ciphertext_validity_proof_account_with_ciphertext
.is_none()
.then_some(ciphertext_validity_proof_data_with_ciphertext);
let range_proof_data = range_proof_account.is_none().then_some(range_proof_data);

(
equality_proof_data,
ciphertext_validity_proof_data,
range_proof_data,
)
};
(
equality_proof_data,
ciphertext_validity_proof_data_with_ciphertext,
range_proof_data,
)
};

let (transfer_amount_auditor_ciphertext_lo, transfer_amount_auditor_ciphertext_hi) =
if let Some(proof_data_with_ciphertext) = ciphertext_validity_proof_data_with_ciphertext
{
(
proof_data_with_ciphertext.ciphertext_lo,
proof_data_with_ciphertext.ciphertext_hi,
)
} else {
// unwrap is safe as long as either `proof_data_with_ciphertext`,
// `proof_account_with_ciphertext` is `Some(..)`, which is guaranteed by the
// previous check
(
ciphertext_validity_proof_account_with_ciphertext
.unwrap()
.ciphertext_lo,
ciphertext_validity_proof_account_with_ciphertext
.unwrap()
.ciphertext_hi,
)
};

// cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`,
// which is guaranteed by the previous check
Expand All @@ -2269,9 +2294,11 @@ where
1,
)
.unwrap();
let ciphertext_validity_proof_data =
ciphertext_validity_proof_data_with_ciphertext.map(|data| data.proof_data);
let ciphertext_validity_proof_location = Self::confidential_transfer_create_proof_location(
ciphertext_validity_proof_data.as_ref(),
ciphertext_validity_proof_account,
ciphertext_validity_proof_account_with_ciphertext.map(|account| &account.proof_account),
2,
)
.unwrap();
Expand All @@ -2292,6 +2319,8 @@ where
self.get_address(),
destination_account,
new_decryptable_available_balance.into(),
&transfer_amount_auditor_ciphertext_lo,
&transfer_amount_auditor_ciphertext_hi,
source_authority,
&multisig_signers,
equality_proof_location,
Expand Down Expand Up @@ -2526,7 +2555,9 @@ where
destination_account: &Pubkey,
source_authority: &Pubkey,
equality_proof_account: Option<&ProofAccount>,
transfer_amount_ciphertext_validity_proof_account: Option<&ProofAccount>,
transfer_amount_ciphertext_validity_proof_account_with_ciphertext: Option<
&ProofAccountWithCiphertext,
>,
percentage_with_cap_proof_account: Option<&ProofAccount>,
fee_ciphertext_validity_proof_account: Option<&ProofAccount>,
range_proof_account: Option<&ProofAccount>,
Expand Down Expand Up @@ -2555,26 +2586,22 @@ where

let (
equality_proof_data,
transfer_amount_ciphertext_validity_proof_data,
transfer_amount_ciphertext_validity_proof_data_with_ciphertext,
percentage_with_cap_proof_data,
fee_ciphertext_validity_proof_data,
range_proof_data,
) = if [
equality_proof_account,
transfer_amount_ciphertext_validity_proof_account,
percentage_with_cap_proof_account,
fee_ciphertext_validity_proof_account,
range_proof_account,
]
.iter()
.all(|proof_account| proof_account.is_some())
) = if equality_proof_account.is_some()
&& transfer_amount_ciphertext_validity_proof_account_with_ciphertext.is_some()
&& percentage_with_cap_proof_account.is_some()
&& fee_ciphertext_validity_proof_account.is_some()
&& range_proof_account.is_some()
{
// is all proofs come from accounts, then skip proof generation
(None, None, None, None, None)
} else {
let TransferWithFeeProofData {
equality_proof_data,
transfer_amount_ciphertext_validity_proof_data,
transfer_amount_ciphertext_validity_proof_data_with_ciphertext,
percentage_with_cap_proof_data,
fee_ciphertext_validity_proof_data,
range_proof_data,
Expand All @@ -2594,10 +2621,10 @@ where
let equality_proof_data = equality_proof_account
.is_none()
.then_some(equality_proof_data);
let transfer_amount_ciphertext_validity_proof_data =
transfer_amount_ciphertext_validity_proof_account
let transfer_amount_ciphertext_validity_proof_data_with_ciphertext =
transfer_amount_ciphertext_validity_proof_account_with_ciphertext
.is_none()
.then_some(transfer_amount_ciphertext_validity_proof_data);
.then_some(transfer_amount_ciphertext_validity_proof_data_with_ciphertext);
let percentage_with_cap_proof_data = percentage_with_cap_proof_account
.is_none()
.then_some(percentage_with_cap_proof_data);
Expand All @@ -2608,13 +2635,35 @@ where

(
equality_proof_data,
transfer_amount_ciphertext_validity_proof_data,
transfer_amount_ciphertext_validity_proof_data_with_ciphertext,
percentage_with_cap_proof_data,
fee_ciphertext_validity_proof_data,
range_proof_data,
)
};

let (transfer_amount_auditor_ciphertext_lo, transfer_amount_auditor_ciphertext_hi) =
if let Some(proof_data_with_ciphertext) =
transfer_amount_ciphertext_validity_proof_data_with_ciphertext
{
(
proof_data_with_ciphertext.ciphertext_lo,
proof_data_with_ciphertext.ciphertext_hi,
)
} else {
// unwrap is safe as long as either `proof_data_with_ciphertext`,
// `proof_account_with_ciphertext` is `Some(..)`, which is guaranteed by the
// previous check
(
transfer_amount_ciphertext_validity_proof_account_with_ciphertext
.unwrap()
.ciphertext_lo,
transfer_amount_ciphertext_validity_proof_account_with_ciphertext
.unwrap()
.ciphertext_hi,
)
};

// cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`,
// which is guaranteed by the previous check
let equality_proof_location = Self::confidential_transfer_create_proof_location(
Expand All @@ -2623,10 +2672,14 @@ where
1,
)
.unwrap();
let transfer_amount_ciphertext_validity_proof_data =
transfer_amount_ciphertext_validity_proof_data_with_ciphertext
.map(|data| data.proof_data);
let transfer_amount_ciphertext_validity_proof_location =
Self::confidential_transfer_create_proof_location(
transfer_amount_ciphertext_validity_proof_data.as_ref(),
transfer_amount_ciphertext_validity_proof_account,
transfer_amount_ciphertext_validity_proof_account_with_ciphertext
.map(|account| &account.proof_account),
2,
)
.unwrap();
Expand Down Expand Up @@ -2660,6 +2713,8 @@ where
self.get_address(),
destination_account,
new_decryptable_available_balance.into(),
&transfer_amount_auditor_ciphertext_lo,
&transfer_amount_auditor_ciphertext_hi,
source_authority,
&multisig_signers,
equality_proof_location,
Expand Down
Loading

0 comments on commit 45b214f

Please sign in to comment.