Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[token-cli] sequentially process confidential transfer withdraw in token-cli #5674

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 60 additions & 19 deletions token/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3409,18 +3409,48 @@ async fn command_deposit_withdraw_confidential_tokens(
state_with_extension.get_extension::<ConfidentialTransferAccount>()?;
let withdraw_account_info = WithdrawAccountInfo::new(extension_state);

let context_state_authority = config.fee_payer()?;
let context_state_keypair = Keypair::new();
let context_state_pubkey = context_state_keypair.pubkey();

let withdraw_proof_data =
withdraw_account_info.generate_proof_data(amount, elgamal_keypair, aes_key)?;

// setup proof
token
.create_withdraw_proof_context_state(
&context_state_pubkey,
&context_state_authority.pubkey(),
&withdraw_proof_data,
&context_state_keypair,
)
.await?;

// do the withdrawal
token
.confidential_transfer_withdraw(
&token_account_address,
&owner,
None,
Some(&context_state_pubkey),
amount,
decimals,
Some(withdraw_account_info),
elgamal_keypair,
aes_key,
&bulk_signers,
)
.await?;

// close context state account
let context_state_authority_pubkey = context_state_authority.pubkey();
let close_context_state_signers = &[context_state_authority];
token
.confidential_transfer_close_context_state(
&context_state_pubkey,
&token_account_address,
&context_state_authority_pubkey,
close_context_state_signers,
)
Comment on lines +3444 to +3453
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to do the withdraw and close in the same transaction? If so, it would be good to do it in this PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good idea!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added issue #5685, which will be addressed in a follow-up PR.

.await?
}
};
Expand Down Expand Up @@ -5315,7 +5345,6 @@ fn app<'a, 'b>(
.validator(is_valid_pubkey)
.value_name("TOKEN_ACCOUNT_ADDRESS")
.takes_value(true)
.conflicts_with("token")
.help("The address of the token account to configure confidential transfers for \
[default: owner's associated token account]")
)
Expand Down Expand Up @@ -9175,23 +9204,35 @@ mod tests {
.unwrap();

// withdraw confidential tokens
//
// NOTE: the test fails due to transaction size limit :(

// let withdraw_amount = 100.0;
//
// process_test_command(
// &config,
// &payer,
// &[
// "spl-token",
// CommandName::WithdrawConfidentialTokens.into(),
// &token_pubkey.to_string(),
// &withdraw_amount.to_string(),
// ],
// )
// .await
// .unwrap();
process_test_command(
&config,
&payer,
&[
"spl-token",
CommandName::ApplyPendingBalance.into(),
"--address",
&destination_account.to_string(),
],
)
.await
.unwrap(); // apply pending balance first

let withdraw_amount = 100.0;

process_test_command(
&config,
&payer,
&[
"spl-token",
CommandName::WithdrawConfidentialTokens.into(),
&token_pubkey.to_string(),
&withdraw_amount.to_string(),
"--address",
&destination_account.to_string(),
],
)
.await
.unwrap();

// disable confidential transfers for mint
process_test_command(
Expand Down
43 changes: 43 additions & 0 deletions token/client/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,49 @@ where
.await
}

/// Create withdraw proof context state account for a confidential transfer withdraw
/// instruction.
pub async fn create_withdraw_proof_context_state<S: Signer>(
&self,
context_state_account: &Pubkey,
context_state_authority: &Pubkey,
withdraw_proof_data: &WithdrawData,
withdraw_proof_signer: &S,
) -> TokenResult<T::Output> {
// create withdraw proof context state
let instruction_type = ProofInstruction::VerifyWithdraw;
let space = size_of::<ProofContextState<WithdrawProofContext>>();
let rent = self
.client
.get_minimum_balance_for_rent_exemption(space)
.await
.map_err(TokenError::Client)?;

let withdraw_proof_context_state_info = ContextStateInfo {
context_state_account,
context_state_authority,
};

self.process_ixs(
&[system_instruction::create_account(
&self.payer.pubkey(),
context_state_account,
rent,
space as u64,
&zk_token_proof_program::id(),
)],
&[withdraw_proof_signer],
)
.await?;

self.process_ixs(
&[instruction_type
.encode_verify_proof(Some(withdraw_proof_context_state_info), withdraw_proof_data)],
&[] as &[&dyn Signer; 0],
)
.await
}

/// Withdraw SPL Tokens from the available balance of a confidential token account using custom
/// keys
#[allow(clippy::too_many_arguments)]
Expand Down
Loading