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

Commit 0f36ed8

Browse files
committed
add auditor ciphertext to transfer instruction data
1 parent af63d47 commit 0f36ed8

File tree

7 files changed

+259
-3
lines changed

7 files changed

+259
-3
lines changed

token/client/src/token.rs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use {
5151
encryption::{
5252
auth_encryption::AeKey,
5353
elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey, ElGamalSecretKey},
54-
pod::elgamal::PodElGamalPubkey,
54+
pod::elgamal::{PodElGamalCiphertext, PodElGamalPubkey},
5555
},
5656
zk_elgamal_proof_program::{
5757
self,
@@ -2201,6 +2201,8 @@ where
22012201
ciphertext_validity_proof_account: Option<&ProofAccount>,
22022202
range_proof_account: Option<&ProofAccount>,
22032203
transfer_amount: u64,
2204+
transfer_amount_auditor_ciphertext_lo: Option<&PodElGamalCiphertext>,
2205+
transfer_amount_auditor_ciphertext_hi: Option<&PodElGamalCiphertext>,
22042206
account_info: Option<TransferAccountInfo>,
22052207
source_elgamal_keypair: &ElGamalKeypair,
22062208
source_aes_key: &AeKey,
@@ -2261,6 +2263,32 @@ where
22612263
)
22622264
};
22632265

2266+
let (transfer_amount_auditor_ciphertext_lo, transfer_amount_auditor_ciphertext_hi) =
2267+
if let Some(proof_data) = ciphertext_validity_proof_data {
2268+
let transfer_amount_auditor_ciphertext_lo = proof_data
2269+
.context_data()
2270+
.grouped_ciphertext_lo
2271+
.try_extract_ciphertext(2)
2272+
.map_err(|_| TokenError::ProofGeneration)?;
2273+
let transfer_amount_auditor_ciphertext_hi = proof_data
2274+
.context_data()
2275+
.grouped_ciphertext_hi
2276+
.try_extract_ciphertext(2)
2277+
.map_err(|_| TokenError::ProofGeneration)?;
2278+
(
2279+
transfer_amount_auditor_ciphertext_lo,
2280+
transfer_amount_auditor_ciphertext_hi,
2281+
)
2282+
} else {
2283+
// the validity proof data is always generated unless
2284+
// `transfer_amount_auditor_ciphertext_lo` and `transfer_amount_auditor_ciphertext_hi`
2285+
// are `Some`, so it is safe to unwrap
2286+
(
2287+
*transfer_amount_auditor_ciphertext_lo.unwrap(),
2288+
*transfer_amount_auditor_ciphertext_hi.unwrap(),
2289+
)
2290+
};
2291+
22642292
// cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`,
22652293
// which is guaranteed by the previous check
22662294
let equality_proof_location = Self::confidential_transfer_create_proof_location(
@@ -2292,6 +2320,8 @@ where
22922320
self.get_address(),
22932321
destination_account,
22942322
new_decryptable_available_balance.into(),
2323+
&transfer_amount_auditor_ciphertext_lo.into(),
2324+
&transfer_amount_auditor_ciphertext_hi.into(),
22952325
source_authority,
22962326
&multisig_signers,
22972327
equality_proof_location,
@@ -2531,6 +2561,8 @@ where
25312561
fee_ciphertext_validity_proof_account: Option<&ProofAccount>,
25322562
range_proof_account: Option<&ProofAccount>,
25332563
transfer_amount: u64,
2564+
transfer_amount_auditor_ciphertext_lo: Option<&PodElGamalCiphertext>,
2565+
transfer_amount_auditor_ciphertext_hi: Option<&PodElGamalCiphertext>,
25342566
account_info: Option<TransferAccountInfo>,
25352567
source_elgamal_keypair: &ElGamalKeypair,
25362568
source_aes_key: &AeKey,
@@ -2615,6 +2647,32 @@ where
26152647
)
26162648
};
26172649

2650+
let (transfer_amount_auditor_ciphertext_lo, transfer_amount_auditor_ciphertext_hi) =
2651+
if let Some(proof_data) = transfer_amount_ciphertext_validity_proof_data {
2652+
let transfer_amount_auditor_ciphertext_lo = proof_data
2653+
.context_data()
2654+
.grouped_ciphertext_lo
2655+
.try_extract_ciphertext(2)
2656+
.map_err(|_| TokenError::ProofGeneration)?;
2657+
let transfer_amount_auditor_ciphertext_hi = proof_data
2658+
.context_data()
2659+
.grouped_ciphertext_hi
2660+
.try_extract_ciphertext(2)
2661+
.map_err(|_| TokenError::ProofGeneration)?;
2662+
(
2663+
transfer_amount_auditor_ciphertext_lo,
2664+
transfer_amount_auditor_ciphertext_hi,
2665+
)
2666+
} else {
2667+
// the validity proof data is always generated unless
2668+
// `transfer_amount_auditor_ciphertext_lo` and `transfer_amount_auditor_ciphertext_hi`
2669+
// are `Some`, so it is safe to unwrap
2670+
(
2671+
*transfer_amount_auditor_ciphertext_lo.unwrap(),
2672+
*transfer_amount_auditor_ciphertext_hi.unwrap(),
2673+
)
2674+
};
2675+
26182676
// cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`,
26192677
// which is guaranteed by the previous check
26202678
let equality_proof_location = Self::confidential_transfer_create_proof_location(
@@ -2660,6 +2718,8 @@ where
26602718
self.get_address(),
26612719
destination_account,
26622720
new_decryptable_available_balance.into(),
2721+
&transfer_amount_auditor_ciphertext_lo.into(),
2722+
&transfer_amount_auditor_ciphertext_hi.into(),
26632723
source_authority,
26642724
&multisig_signers,
26652725
equality_proof_location,

token/program-2022-test/tests/confidential_transfer.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,6 +1321,8 @@ async fn confidential_transfer_with_option<S: Signers>(
13211321
None,
13221322
transfer_amount,
13231323
None,
1324+
None,
1325+
None,
13241326
source_elgamal_keypair,
13251327
source_aes_key,
13261328
destination_elgamal_pubkey,
@@ -1350,6 +1352,17 @@ async fn confidential_transfer_with_option<S: Signers>(
13501352
)
13511353
.unwrap();
13521354

1355+
let transfer_amount_auditor_ciphertext_lo = ciphertext_validity_proof_data
1356+
.context_data()
1357+
.grouped_ciphertext_lo
1358+
.try_extract_ciphertext(2)
1359+
.unwrap();
1360+
let transfer_amount_auditor_ciphertext_hi = ciphertext_validity_proof_data
1361+
.context_data()
1362+
.grouped_ciphertext_hi
1363+
.try_extract_ciphertext(2)
1364+
.unwrap();
1365+
13531366
let equality_proof_record_account = Keypair::new();
13541367
let ciphertext_validity_proof_record_account = Keypair::new();
13551368
let range_proof_record_account = Keypair::new();
@@ -1418,6 +1431,8 @@ async fn confidential_transfer_with_option<S: Signers>(
14181431
Some(&ciphertext_validity_proof_account),
14191432
Some(&range_proof_account),
14201433
transfer_amount,
1434+
Some(&transfer_amount_auditor_ciphertext_lo),
1435+
Some(&transfer_amount_auditor_ciphertext_hi),
14211436
None,
14221437
source_elgamal_keypair,
14231438
source_aes_key,
@@ -1480,6 +1495,17 @@ async fn confidential_transfer_with_option<S: Signers>(
14801495
)
14811496
.unwrap();
14821497

1498+
let transfer_amount_auditor_ciphertext_lo = ciphertext_validity_proof_data
1499+
.context_data()
1500+
.grouped_ciphertext_lo
1501+
.try_extract_ciphertext(2)
1502+
.unwrap();
1503+
let transfer_amount_auditor_ciphertext_hi = ciphertext_validity_proof_data
1504+
.context_data()
1505+
.grouped_ciphertext_hi
1506+
.try_extract_ciphertext(2)
1507+
.unwrap();
1508+
14831509
let equality_proof_context_account = Keypair::new();
14841510
let ciphertext_validity_proof_context_account = Keypair::new();
14851511
let range_proof_context_account = Keypair::new();
@@ -1542,6 +1568,8 @@ async fn confidential_transfer_with_option<S: Signers>(
15421568
Some(&ciphertext_validity_proof_context_proof_account),
15431569
Some(&range_proof_context_proof_account),
15441570
transfer_amount,
1571+
Some(&transfer_amount_auditor_ciphertext_lo),
1572+
Some(&transfer_amount_auditor_ciphertext_hi),
15451573
None,
15461574
source_elgamal_keypair,
15471575
source_aes_key,
@@ -1872,6 +1900,8 @@ async fn confidential_transfer_with_fee_with_option<S: Signers>(
18721900
None,
18731901
transfer_amount,
18741902
None,
1903+
None,
1904+
None,
18751905
source_elgamal_keypair,
18761906
source_aes_key,
18771907
destination_elgamal_pubkey,
@@ -1909,6 +1939,19 @@ async fn confidential_transfer_with_fee_with_option<S: Signers>(
19091939
)
19101940
.unwrap();
19111941

1942+
let transfer_amount_auditor_ciphertext_lo =
1943+
transfer_amount_ciphertext_validity_proof_data
1944+
.context_data()
1945+
.grouped_ciphertext_lo
1946+
.try_extract_ciphertext(2)
1947+
.unwrap();
1948+
let transfer_amount_auditor_ciphertext_hi =
1949+
transfer_amount_ciphertext_validity_proof_data
1950+
.context_data()
1951+
.grouped_ciphertext_hi
1952+
.try_extract_ciphertext(2)
1953+
.unwrap();
1954+
19121955
let equality_proof_record_account = Keypair::new();
19131956
let transfer_amount_ciphertext_validity_proof_record_account = Keypair::new();
19141957
let fee_sigma_proof_record_account = Keypair::new();
@@ -2013,6 +2056,8 @@ async fn confidential_transfer_with_fee_with_option<S: Signers>(
20132056
Some(&fee_ciphertext_validity_proof_account),
20142057
Some(&range_proof_account),
20152058
transfer_amount,
2059+
Some(&transfer_amount_auditor_ciphertext_lo),
2060+
Some(&transfer_amount_auditor_ciphertext_hi),
20162061
None,
20172062
source_elgamal_keypair,
20182063
source_aes_key,
@@ -2103,6 +2148,19 @@ async fn confidential_transfer_with_fee_with_option<S: Signers>(
21032148
)
21042149
.unwrap();
21052150

2151+
let transfer_amount_auditor_ciphertext_lo =
2152+
transfer_amount_ciphertext_validity_proof_data
2153+
.context_data()
2154+
.grouped_ciphertext_lo
2155+
.try_extract_ciphertext(2)
2156+
.unwrap();
2157+
let transfer_amount_auditor_ciphertext_hi =
2158+
transfer_amount_ciphertext_validity_proof_data
2159+
.context_data()
2160+
.grouped_ciphertext_hi
2161+
.try_extract_ciphertext(2)
2162+
.unwrap();
2163+
21062164
let equality_proof_context_account = Keypair::new();
21072165
let transfer_amount_ciphertext_validity_proof_context_account = Keypair::new();
21082166
let percentage_with_cap_proof_context_account = Keypair::new();
@@ -2200,6 +2258,8 @@ async fn confidential_transfer_with_fee_with_option<S: Signers>(
22002258
Some(&fee_ciphertext_validity_proof_context_proof_account),
22012259
Some(&range_proof_context_proof_account),
22022260
transfer_amount,
2261+
Some(&transfer_amount_auditor_ciphertext_lo),
2262+
Some(&transfer_amount_auditor_ciphertext_hi),
22032263
None,
22042264
source_elgamal_keypair,
22052265
source_aes_key,

token/program-2022-test/tests/confidential_transfer_fee.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,8 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_mint_with_option(
690690
None,
691691
100,
692692
None,
693+
None,
694+
None,
693695
&alice_meta.elgamal_keypair,
694696
&alice_meta.aes_key,
695697
bob_meta.elgamal_keypair.pubkey(),
@@ -1016,6 +1018,8 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_accounts_with_optio
10161018
None,
10171019
100,
10181020
None,
1021+
None,
1022+
None,
10191023
&alice_meta.elgamal_keypair,
10201024
&alice_meta.aes_key,
10211025
bob_meta.elgamal_keypair.pubkey(),
@@ -1155,6 +1159,8 @@ async fn confidential_transfer_harvest_withheld_tokens_to_mint() {
11551159
None,
11561160
100,
11571161
None,
1162+
None,
1163+
None,
11581164
&alice_meta.elgamal_keypair,
11591165
&alice_meta.aes_key,
11601166
bob_meta.elgamal_keypair.pubkey(),

token/program-2022-test/tests/transfer_hook.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ async fn success_confidential_transfer() {
10041004
None,
10051005
amount,
10061006
None,
1007+
None,
1008+
None,
10071009
&alice_meta.elgamal_keypair,
10081010
&alice_meta.aes_key,
10091011
bob_meta.elgamal_keypair.pubkey(),

token/program-2022/src/extension/confidential_transfer/instruction.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,12 @@ pub struct TransferInstructionData {
619619
/// The new source decryptable balance if the transfer succeeds
620620
#[cfg_attr(feature = "serde-traits", serde(with = "aeciphertext_fromstr"))]
621621
pub new_source_decryptable_available_balance: DecryptableBalance,
622+
/// The transfer amount encrypted under the auditor ElGamal public key
623+
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
624+
pub transfer_amount_auditor_ciphertext_lo: PodElGamalCiphertext,
625+
/// The transfer amount encrypted under the auditor ElGamal public key
626+
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
627+
pub transfer_amount_auditor_ciphertext_hi: PodElGamalCiphertext,
622628
/// Relative location of the
623629
/// `ProofInstruction::VerifyCiphertextCommitmentEquality` instruction
624630
/// to the `Transfer` instruction in the transaction. If the offset is
@@ -658,6 +664,12 @@ pub struct TransferWithFeeInstructionData {
658664
/// The new source decryptable balance if the transfer succeeds
659665
#[cfg_attr(feature = "serde-traits", serde(with = "aeciphertext_fromstr"))]
660666
pub new_source_decryptable_available_balance: DecryptableBalance,
667+
/// The transfer amount encrypted under the auditor ElGamal public key
668+
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
669+
pub transfer_amount_auditor_ciphertext_lo: PodElGamalCiphertext,
670+
/// The transfer amount encrypted under the auditor ElGamal public key
671+
#[cfg_attr(feature = "serde-traits", serde(with = "elgamalciphertext_fromstr"))]
672+
pub transfer_amount_auditor_ciphertext_hi: PodElGamalCiphertext,
661673
/// Relative location of the
662674
/// `ProofInstruction::VerifyCiphertextCommitmentEquality` instruction
663675
/// to the `TransferWithFee` instruction in the transaction. If the offset
@@ -1151,6 +1163,8 @@ pub fn inner_transfer(
11511163
mint: &Pubkey,
11521164
destination_token_account: &Pubkey,
11531165
new_source_decryptable_available_balance: DecryptableBalance,
1166+
transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext,
1167+
transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext,
11541168
authority: &Pubkey,
11551169
multisig_signers: &[&Pubkey],
11561170
equality_proof_data_location: ProofLocation<CiphertextCommitmentEqualityProofData>,
@@ -1231,6 +1245,8 @@ pub fn inner_transfer(
12311245
ConfidentialTransferInstruction::Transfer,
12321246
&TransferInstructionData {
12331247
new_source_decryptable_available_balance,
1248+
transfer_amount_auditor_ciphertext_lo: *transfer_amount_auditor_ciphertext_lo,
1249+
transfer_amount_auditor_ciphertext_hi: *transfer_amount_auditor_ciphertext_hi,
12341250
equality_proof_instruction_offset,
12351251
ciphertext_validity_proof_instruction_offset,
12361252
range_proof_instruction_offset,
@@ -1246,6 +1262,8 @@ pub fn transfer(
12461262
mint: &Pubkey,
12471263
destination_token_account: &Pubkey,
12481264
new_source_decryptable_available_balance: DecryptableBalance,
1265+
transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext,
1266+
transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext,
12491267
authority: &Pubkey,
12501268
multisig_signers: &[&Pubkey],
12511269
equality_proof_data_location: ProofLocation<CiphertextCommitmentEqualityProofData>,
@@ -1260,6 +1278,8 @@ pub fn transfer(
12601278
mint,
12611279
destination_token_account,
12621280
new_source_decryptable_available_balance,
1281+
transfer_amount_auditor_ciphertext_lo,
1282+
transfer_amount_auditor_ciphertext_hi,
12631283
authority,
12641284
multisig_signers,
12651285
equality_proof_data_location,
@@ -1484,6 +1504,8 @@ pub fn inner_transfer_with_fee(
14841504
mint: &Pubkey,
14851505
destination_token_account: &Pubkey,
14861506
new_source_decryptable_available_balance: DecryptableBalance,
1507+
transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext,
1508+
transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext,
14871509
authority: &Pubkey,
14881510
multisig_signers: &[&Pubkey],
14891511
equality_proof_data_location: ProofLocation<CiphertextCommitmentEqualityProofData>,
@@ -1597,6 +1619,8 @@ pub fn inner_transfer_with_fee(
15971619
ConfidentialTransferInstruction::TransferWithFee,
15981620
&TransferWithFeeInstructionData {
15991621
new_source_decryptable_available_balance,
1622+
transfer_amount_auditor_ciphertext_lo: *transfer_amount_auditor_ciphertext_lo,
1623+
transfer_amount_auditor_ciphertext_hi: *transfer_amount_auditor_ciphertext_hi,
16001624
equality_proof_instruction_offset,
16011625
transfer_amount_ciphertext_validity_proof_instruction_offset,
16021626
fee_sigma_proof_instruction_offset,
@@ -1614,6 +1638,8 @@ pub fn transfer_with_fee(
16141638
mint: &Pubkey,
16151639
destination_token_account: &Pubkey,
16161640
new_source_decryptable_available_balance: DecryptableBalance,
1641+
transfer_amount_auditor_ciphertext_lo: &PodElGamalCiphertext,
1642+
transfer_amount_auditor_ciphertext_hi: &PodElGamalCiphertext,
16171643
authority: &Pubkey,
16181644
multisig_signers: &[&Pubkey],
16191645
equality_proof_data_location: ProofLocation<CiphertextCommitmentEqualityProofData>,
@@ -1632,6 +1658,8 @@ pub fn transfer_with_fee(
16321658
mint,
16331659
destination_token_account,
16341660
new_source_decryptable_available_balance,
1661+
transfer_amount_auditor_ciphertext_lo,
1662+
transfer_amount_auditor_ciphertext_hi,
16351663
authority,
16361664
multisig_signers,
16371665
equality_proof_data_location,

0 commit comments

Comments
 (0)