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

Commit d0eff43

Browse files
[token-2022] Add support for record program for Transfer and TransferWithFee instructions (#7127)
* refactor out verify proof logic into a separate function * clean up transfer proof verification * re-organize confidential transfer instruction into `Transfer` and `TransferWithFee` * use `verify_and_extract_context` function directly * update token client * update program-2022 tests * update token-cli * cargo fmt * Update token/program-2022/src/extension/confidential_transfer/instruction.rs Co-authored-by: Jon C <[email protected]> --------- Co-authored-by: Jon C <[email protected]>
1 parent 1f988aa commit d0eff43

File tree

15 files changed

+2343
-3478
lines changed

15 files changed

+2343
-3478
lines changed

token/cli/src/command.rs

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ use {
4141
account_info::{
4242
ApplyPendingBalanceAccountInfo, TransferAccountInfo, WithdrawAccountInfo,
4343
},
44-
instruction::TransferSplitContextStateAccounts,
4544
ConfidentialTransferAccount, ConfidentialTransferMint,
4645
},
4746
confidential_transfer_fee::ConfidentialTransferFeeConfig,
@@ -1575,6 +1574,7 @@ async fn command_transfer(
15751574
});
15761575

15771576
let context_state_authority = config.fee_payer()?;
1577+
let context_state_authority_pubkey = context_state_authority.pubkey();
15781578
let equality_proof_context_state_account = Keypair::new();
15791579
let equality_proof_pubkey = equality_proof_context_state_account.pubkey();
15801580
let ciphertext_validity_proof_context_state_account = Keypair::new();
@@ -1583,91 +1583,90 @@ async fn command_transfer(
15831583
let range_proof_context_state_account = Keypair::new();
15841584
let range_proof_pubkey = range_proof_context_state_account.pubkey();
15851585

1586-
let transfer_context_state_accounts = TransferSplitContextStateAccounts {
1587-
equality_proof: &equality_proof_pubkey,
1588-
ciphertext_validity_proof: &ciphertext_validity_proof_pubkey,
1589-
range_proof: &range_proof_pubkey,
1590-
authority: &context_state_authority.pubkey(),
1591-
no_op_on_uninitialized_split_context_state: false,
1592-
close_split_context_state_accounts: None,
1593-
};
1594-
15951586
let state = token.get_account_info(&sender).await.unwrap();
15961587
let extension = state
15971588
.get_extension::<ConfidentialTransferAccount>()
15981589
.unwrap();
15991590
let transfer_account_info = TransferAccountInfo::new(extension);
16001591

1601-
let (
1602-
equality_proof_data,
1603-
ciphertext_validity_proof_data,
1604-
range_proof_data,
1605-
source_decrypt_handles,
1606-
) = transfer_account_info
1607-
.generate_split_transfer_proof_data(
1608-
transfer_balance,
1609-
&args.sender_elgamal_keypair,
1610-
&args.sender_aes_key,
1611-
&recipient_elgamal_pubkey,
1612-
auditor_elgamal_pubkey.as_ref(),
1613-
)
1614-
.unwrap();
1592+
let (equality_proof_data, ciphertext_validity_proof_data, range_proof_data) =
1593+
transfer_account_info
1594+
.generate_split_transfer_proof_data(
1595+
transfer_balance,
1596+
&args.sender_elgamal_keypair,
1597+
&args.sender_aes_key,
1598+
&recipient_elgamal_pubkey,
1599+
auditor_elgamal_pubkey.as_ref(),
1600+
)
1601+
.unwrap();
16151602

16161603
// setup proofs
16171604
let _ = try_join!(
16181605
token.create_range_proof_context_state_for_transfer(
1619-
transfer_context_state_accounts,
1606+
&range_proof_pubkey,
1607+
&context_state_authority_pubkey,
16201608
&range_proof_data,
16211609
&range_proof_context_state_account,
16221610
),
16231611
token.create_equality_proof_context_state_for_transfer(
1624-
transfer_context_state_accounts,
1612+
&equality_proof_pubkey,
1613+
&context_state_authority_pubkey,
16251614
&equality_proof_data,
16261615
&equality_proof_context_state_account,
16271616
),
16281617
token.create_ciphertext_validity_proof_context_state_for_transfer(
1629-
transfer_context_state_accounts,
1618+
&ciphertext_validity_proof_pubkey,
1619+
&context_state_authority_pubkey,
16301620
&ciphertext_validity_proof_data,
16311621
&ciphertext_validity_proof_context_state_account,
16321622
)
16331623
)?;
16341624

16351625
// do the transfer
1626+
let equality_proof_context_proof_account =
1627+
ProofAccount::ContextAccount(equality_proof_pubkey);
1628+
let ciphertext_validity_proof_context_proof_account =
1629+
ProofAccount::ContextAccount(ciphertext_validity_proof_pubkey);
1630+
let range_proof_context_proof_account =
1631+
ProofAccount::ContextAccount(range_proof_pubkey);
1632+
16361633
let transfer_result = token
1637-
.confidential_transfer_transfer_with_split_proofs(
1634+
.confidential_transfer_transfer(
16381635
&sender,
16391636
&recipient_token_account,
16401637
&sender_owner,
1641-
transfer_context_state_accounts,
1638+
Some(&equality_proof_context_proof_account),
1639+
Some(&ciphertext_validity_proof_context_proof_account),
1640+
Some(&range_proof_context_proof_account),
16421641
transfer_balance,
16431642
Some(transfer_account_info),
1643+
&args.sender_elgamal_keypair,
16441644
&args.sender_aes_key,
1645-
&source_decrypt_handles,
1645+
&recipient_elgamal_pubkey,
1646+
auditor_elgamal_pubkey.as_ref(),
16461647
&bulk_signers,
16471648
)
16481649
.await?;
16491650

16501651
// close context state accounts
1651-
let context_state_authority_pubkey = context_state_authority.pubkey();
1652-
let close_context_state_signers = &[context_state_authority];
16531652
let _ = try_join!(
16541653
token.confidential_transfer_close_context_state(
16551654
&equality_proof_pubkey,
16561655
&sender,
16571656
&context_state_authority_pubkey,
1658-
close_context_state_signers,
1657+
&context_state_authority,
16591658
),
16601659
token.confidential_transfer_close_context_state(
16611660
&ciphertext_validity_proof_pubkey,
16621661
&sender,
16631662
&context_state_authority_pubkey,
1664-
close_context_state_signers,
1663+
&context_state_authority,
16651664
),
16661665
token.confidential_transfer_close_context_state(
16671666
&range_proof_pubkey,
16681667
&sender,
16691668
&context_state_authority_pubkey,
1670-
close_context_state_signers,
1669+
&context_state_authority,
16711670
),
16721671
)?;
16731672

@@ -3369,13 +3368,12 @@ async fn command_deposit_withdraw_confidential_tokens(
33693368

33703369
// close context state account
33713370
let context_state_authority_pubkey = context_state_authority.pubkey();
3372-
let close_context_state_signers = &[context_state_authority];
33733371
token
33743372
.confidential_transfer_close_context_state(
33753373
&context_state_pubkey,
33763374
&token_account_address,
33773375
&context_state_authority_pubkey,
3378-
close_context_state_signers,
3376+
&context_state_authority,
33793377
)
33803378
.await?
33813379
}

token/client/src/proof_generation.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ use {
1010
spl_token_2022::{
1111
error::TokenError,
1212
extension::confidential_transfer::{
13-
ciphertext_extraction::{transfer_amount_source_ciphertext, SourceDecryptHandles},
13+
ciphertext_extraction::transfer_amount_source_ciphertext,
1414
processor::verify_and_split_deposit_amount,
1515
},
1616
solana_zk_token_sdk::{
1717
encryption::{
1818
auth_encryption::{AeCiphertext, AeKey},
19-
elgamal::{DecryptHandle, ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey},
19+
elgamal::{ElGamalCiphertext, ElGamalKeypair, ElGamalPubkey},
2020
grouped_elgamal::GroupedElGamal,
2121
pedersen::{Pedersen, PedersenCommitment, PedersenOpening},
2222
},
@@ -25,7 +25,8 @@ use {
2525
try_combine_lo_hi_commitments, try_combine_lo_hi_openings, FeeEncryption,
2626
FeeParameters, TransferAmountCiphertext,
2727
},
28-
BatchedGroupedCiphertext2HandlesValidityProofData, BatchedRangeProofU256Data,
28+
BatchedGroupedCiphertext2HandlesValidityProofData,
29+
BatchedGroupedCiphertext3HandlesValidityProofData, BatchedRangeProofU256Data,
2930
CiphertextCommitmentEqualityProofData, FeeSigmaProofData,
3031
},
3132
zk_token_elgamal::ops::subtract_with_lo_hi,
@@ -53,11 +54,10 @@ pub fn transfer_with_fee_split_proof_data(
5354
) -> Result<
5455
(
5556
CiphertextCommitmentEqualityProofData,
56-
BatchedGroupedCiphertext2HandlesValidityProofData,
57+
BatchedGroupedCiphertext3HandlesValidityProofData,
5758
FeeSigmaProofData,
5859
BatchedGroupedCiphertext2HandlesValidityProofData,
5960
BatchedRangeProofU256Data,
60-
SourceDecryptHandles,
6161
),
6262
TokenError,
6363
> {
@@ -126,33 +126,31 @@ pub fn transfer_with_fee_split_proof_data(
126126
)
127127
.map_err(|_| TokenError::ProofGeneration)?;
128128

129-
// create source decrypt handle
130-
let source_decrypt_handle_lo =
131-
DecryptHandle::new(source_elgamal_keypair.pubkey(), &transfer_amount_opening_lo);
132-
let source_decrypt_handle_hi =
133-
DecryptHandle::new(source_elgamal_keypair.pubkey(), &transfer_amount_opening_hi);
134-
135-
let source_decrypt_handles = SourceDecryptHandles {
136-
lo: source_decrypt_handle_lo.into(),
137-
hi: source_decrypt_handle_hi.into(),
138-
};
139-
140-
// encrypt the transfer amount under the destination and auditor ElGamal public
141-
// key
129+
// encrypt the transfer amount under the source, destination and auditor ElGamal
130+
// public key
142131
let transfer_amount_destination_auditor_ciphertext_lo = GroupedElGamal::encrypt_with(
143-
[destination_elgamal_pubkey, auditor_elgamal_pubkey],
132+
[
133+
source_elgamal_keypair.pubkey(),
134+
destination_elgamal_pubkey,
135+
auditor_elgamal_pubkey,
136+
],
144137
transfer_amount_lo,
145138
&transfer_amount_opening_lo,
146139
);
147140
let transfer_amount_destination_auditor_ciphertext_hi = GroupedElGamal::encrypt_with(
148-
[destination_elgamal_pubkey, auditor_elgamal_pubkey],
141+
[
142+
source_elgamal_keypair.pubkey(),
143+
destination_elgamal_pubkey,
144+
auditor_elgamal_pubkey,
145+
],
149146
transfer_amount_hi,
150147
&transfer_amount_opening_hi,
151148
);
152149

153150
// generate transfer amount ciphertext validity data
154151
let transfer_amount_ciphertext_validity_proof_data =
155-
BatchedGroupedCiphertext2HandlesValidityProofData::new(
152+
BatchedGroupedCiphertext3HandlesValidityProofData::new(
153+
source_elgamal_keypair.pubkey(),
156154
destination_elgamal_pubkey,
157155
auditor_elgamal_pubkey,
158156
&transfer_amount_destination_auditor_ciphertext_lo,
@@ -332,7 +330,6 @@ pub fn transfer_with_fee_split_proof_data(
332330
fee_sigma_proof_data,
333331
fee_ciphertext_validity_proof_data,
334332
range_proof_data,
335-
source_decrypt_handles,
336333
))
337334
}
338335

0 commit comments

Comments
 (0)