diff --git a/Cargo.lock b/Cargo.lock index 18cb66f8919..9f546cb9f04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7595,7 +7595,6 @@ dependencies = [ "spl-instruction-padding", "spl-memo 5.0.0", "spl-pod 0.3.1", - "spl-record", "spl-tlv-account-resolution 0.7.0", "spl-token-2022 4.0.1", "spl-token-client", @@ -7650,8 +7649,6 @@ name = "spl-token-client" version = "0.11.0" dependencies = [ "async-trait", - "bincode", - "bytemuck", "curve25519-dalek", "futures 0.3.30", "futures-util", @@ -7663,7 +7660,6 @@ dependencies = [ "solana-sdk", "spl-associated-token-account 4.0.0", "spl-memo 5.0.0", - "spl-record", "spl-token 6.0.0", "spl-token-2022 4.0.1", "spl-token-group-interface 0.3.0", diff --git a/token/cli/src/command.rs b/token/cli/src/command.rs index 1faf086127a..82abe3910f7 100644 --- a/token/cli/src/command.rs +++ b/token/cli/src/command.rs @@ -69,7 +69,6 @@ use { }, spl_token_client::{ client::{ProgramRpcClientSendTransaction, RpcClientResponse}, - proof_generation::ProofAccount, token::{ComputeUnitLimit, ExtensionInitializationParams, Token}, }, spl_token_group_interface::state::TokenGroup, @@ -3349,7 +3348,7 @@ async fn command_deposit_withdraw_confidential_tokens( .confidential_transfer_withdraw( &token_account_address, &owner, - Some(&ProofAccount::ContextAccount(context_state_pubkey)), + Some(&context_state_pubkey), amount, decimals, Some(withdraw_account_info), diff --git a/token/client/Cargo.toml b/token/client/Cargo.toml index bca57598627..762b2f3e4cb 100644 --- a/token/client/Cargo.toml +++ b/token/client/Cargo.toml @@ -9,8 +9,6 @@ version = "0.11.0" [dependencies] async-trait = "0.1" -bincode = "1.3.2" -bytemuck = "1.16.3" curve25519-dalek = "3.2.1" futures = "0.3.30" futures-util = "0.3" @@ -28,7 +26,6 @@ spl-associated-token-account = { version = "4.0.0", path = "../../associated-tok spl-memo = { version = "5.0", path = "../../memo/program", features = [ "no-entrypoint", ] } -spl-record = { version = "0.2.0", path = "../../record/program", features = ["no-entrypoint"] } spl-token = { version = "6.0", path = "../program", features = [ "no-entrypoint", ] } diff --git a/token/client/src/proof_generation.rs b/token/client/src/proof_generation.rs index cd5f540c7ad..3c41d5094eb 100644 --- a/token/client/src/proof_generation.rs +++ b/token/client/src/proof_generation.rs @@ -6,7 +6,6 @@ use { curve25519_dalek::scalar::Scalar, - solana_sdk::pubkey::Pubkey, spl_token_2022::{ error::TokenError, extension::confidential_transfer::{ @@ -33,11 +32,6 @@ use { }, }; -pub enum ProofAccount { - ContextAccount(Pubkey), - RecordAccount(Pubkey, u32), -} - /// The main logic to create the five split proof data for a transfer with fee. #[allow(clippy::too_many_arguments)] pub fn transfer_with_fee_split_proof_data( diff --git a/token/client/src/token.rs b/token/client/src/token.rs index c65b2b40812..a9fefc21f70 100644 --- a/token/client/src/token.rs +++ b/token/client/src/token.rs @@ -4,9 +4,8 @@ use { ProgramClient, ProgramClientError, SendTransaction, SimulateTransaction, SimulationResult, }, - proof_generation::{transfer_with_fee_split_proof_data, ProofAccount}, + proof_generation::transfer_with_fee_split_proof_data, }, - bytemuck::bytes_of, futures::{future::join_all, try_join}, futures_util::TryFutureExt, solana_program_test::tokio::time, @@ -16,11 +15,9 @@ use { hash::Hash, instruction::{AccountMeta, Instruction}, message::Message, - packet::PACKET_DATA_SIZE, program_error::ProgramError, program_pack::Pack, pubkey::Pubkey, - signature::Signature, signer::{signers::Signers, Signer, SignerError}, system_instruction, transaction::Transaction, @@ -31,7 +28,6 @@ use { create_associated_token_account, create_associated_token_account_idempotent, }, }, - spl_record::state::RecordData, spl_token_2022::{ extension::{ confidential_transfer::{ @@ -55,7 +51,7 @@ use { BaseStateWithExtensions, Extension, ExtensionType, StateWithExtensionsOwned, }, instruction, offchain, - proof::{ProofData, ProofLocation}, + proof::ProofLocation, solana_zk_token_sdk::{ encryption::{ auth_encryption::AeKey, @@ -1896,7 +1892,7 @@ where &self, account: &Pubkey, authority: &Pubkey, - proof_account: Option<&ProofAccount>, + context_state_account: Option<&Pubkey>, maximum_pending_balance_credit_counter: Option<u64>, elgamal_keypair: &ElGamalKeypair, aes_key: &AeKey, @@ -1910,7 +1906,7 @@ where let maximum_pending_balance_credit_counter = maximum_pending_balance_credit_counter .unwrap_or(DEFAULT_MAXIMUM_PENDING_BALANCE_CREDIT_COUNTER); - let proof_data = if proof_account.is_some() { + let proof_data = if context_state_account.is_some() { None } else { Some( @@ -1919,11 +1915,12 @@ where ) }; - // cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`, - // which is guaranteed by the previous check - let proof_location = - Self::confidential_transfer_create_proof_location(proof_data.as_ref(), proof_account) - .unwrap(); + let proof_location = if let Some(proof_data_temp) = proof_data.as_ref() { + ProofLocation::InstructionOffset(1.try_into().unwrap(), proof_data_temp) + } else { + let context_state_account = context_state_account.unwrap(); + ProofLocation::ContextStateAccount(context_state_account) + }; let decryptable_balance = aes_key.encrypt(0); @@ -1972,7 +1969,7 @@ where &self, account: &Pubkey, authority: &Pubkey, - proof_account: Option<&ProofAccount>, + context_state_account: Option<&Pubkey>, account_info: Option<EmptyAccountAccountInfo>, elgamal_keypair: &ElGamalKeypair, signing_keypairs: &S, @@ -1989,7 +1986,7 @@ where EmptyAccountAccountInfo::new(confidential_transfer_account) }; - let proof_data = if proof_account.is_some() { + let proof_data = if context_state_account.is_some() { None } else { Some( @@ -1999,11 +1996,12 @@ where ) }; - // cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`, - // which is guaranteed by the previous check - let proof_location = - Self::confidential_transfer_create_proof_location(proof_data.as_ref(), proof_account) - .unwrap(); + let proof_location = if let Some(proof_data_temp) = proof_data.as_ref() { + ProofLocation::InstructionOffset(1.try_into().unwrap(), proof_data_temp) + } else { + let context_state_account = context_state_account.unwrap(); + ProofLocation::ContextStateAccount(context_state_account) + }; self.process_ixs( &confidential_transfer::instruction::empty_account( @@ -2053,7 +2051,7 @@ where &self, account: &Pubkey, authority: &Pubkey, - proof_account: Option<&ProofAccount>, + context_state_account: Option<&Pubkey>, withdraw_amount: u64, decimals: u8, account_info: Option<WithdrawAccountInfo>, @@ -2073,7 +2071,7 @@ where WithdrawAccountInfo::new(confidential_transfer_account) }; - let proof_data = if proof_account.is_some() { + let proof_data = if context_state_account.is_some() { None } else { Some( @@ -2083,11 +2081,12 @@ where ) }; - // cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`, - // which is guaranteed by the previous check - let proof_location = - Self::confidential_transfer_create_proof_location(proof_data.as_ref(), proof_account) - .unwrap(); + let proof_location = if let Some(proof_data_temp) = proof_data.as_ref() { + ProofLocation::InstructionOffset(1.try_into().unwrap(), proof_data_temp) + } else { + let context_state_account = context_state_account.unwrap(); + ProofLocation::ContextStateAccount(context_state_account) + }; let new_decryptable_available_balance = account_info .new_decryptable_available_balance(withdraw_amount, aes_key) @@ -2174,7 +2173,7 @@ where source_account: &Pubkey, destination_account: &Pubkey, source_authority: &Pubkey, - proof_account: Option<&ProofAccount>, + context_state_account: Option<&Pubkey>, transfer_amount: u64, account_info: Option<TransferAccountInfo>, source_elgamal_keypair: &ElGamalKeypair, @@ -2195,7 +2194,7 @@ where TransferAccountInfo::new(confidential_transfer_account) }; - let proof_data = if proof_account.is_some() { + let proof_data = if context_state_account.is_some() { None } else { Some( @@ -2211,11 +2210,12 @@ where ) }; - // cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`, - // which is guaranteed by the previous check - let proof_location = - Self::confidential_transfer_create_proof_location(proof_data.as_ref(), proof_account) - .unwrap(); + let proof_location = if let Some(proof_data_temp) = proof_data.as_ref() { + ProofLocation::InstructionOffset(1.try_into().unwrap(), proof_data_temp) + } else { + let context_state_account = context_state_account.unwrap(); + ProofLocation::ContextStateAccount(context_state_account) + }; let new_decryptable_available_balance = account_info .new_decryptable_available_balance(transfer_amount, source_aes_key) @@ -2405,110 +2405,6 @@ where ) } - /// Create a record account containing zero-knowledge proof needed for a - /// confidential transfer. - pub async fn confidential_transfer_create_record_account< - S: Signer, - ZK: Pod + ZkProofData<U>, - U: Pod, - >( - &self, - record_account: &Pubkey, - record_authority: &Pubkey, - proof_data: &ZK, - record_account_signer: &S, - record_authority_signer: &S, - ) -> TokenResult<Vec<T::Output>> { - let proof_data = bytes_of(proof_data); - let space = proof_data - .len() - .saturating_add(RecordData::WRITABLE_START_INDEX); - let rent = self - .client - .get_minimum_balance_for_rent_exemption(space) - .await - .map_err(TokenError::Client)?; - - // A closure that constructs a vector of instructions needed to create and write - // to record accounts. The closure is defined as a convenience function - // to be fed into the function `calculate_record_max_chunk_size`. - let create_record_instructions = |first_instruction: bool, bytes: &[u8], offset: u64| { - let mut ixs = vec![]; - if first_instruction { - ixs.push(system_instruction::create_account( - &self.payer.pubkey(), - record_account, - rent, - space as u64, - &spl_record::id(), - )); - ixs.push(spl_record::instruction::initialize( - record_account, - record_authority, - )); - } - ixs.push(spl_record::instruction::write( - record_account, - record_authority, - offset, - bytes, - )); - ixs - }; - let first_chunk_size = calculate_record_max_chunk_size(create_record_instructions, true); - let (first_chunk, rest) = if space <= first_chunk_size { - (proof_data, &[] as &[u8]) - } else { - proof_data.split_at(first_chunk_size) - }; - - let first_ixs = create_record_instructions(true, first_chunk, 0); - self.process_ixs( - &first_ixs, - &[record_account_signer, record_authority_signer], - ) - .await?; - - let subsequent_chunk_size = - calculate_record_max_chunk_size(create_record_instructions, false); - let mut record_offset = first_chunk_size; - let mut ixs_batch = vec![]; - for chunk in rest.chunks(subsequent_chunk_size) { - ixs_batch.push(create_record_instructions( - false, - chunk, - record_offset as u64, - )); - record_offset = record_offset.saturating_add(chunk.len()); - } - - let futures = ixs_batch - .into_iter() - .map(|ixs| async move { self.process_ixs(&ixs, &[record_authority_signer]).await }) - .collect::<Vec<_>>(); - - join_all(futures).await.into_iter().collect() - } - - /// Close a record account. - pub async fn confidential_transfer_close_record_account<S: Signer>( - &self, - record_account: &Pubkey, - record_authority: &Pubkey, - receiver: &Pubkey, - record_authority_signer: &S, - ) -> TokenResult<T::Output> { - self.process_ixs( - &[spl_record::instruction::close_account( - record_account, - record_authority, - receiver, - )], - &[record_authority_signer], - ) - .await - } - /// Create equality proof context state account for a confidential transfer. #[allow(clippy::too_many_arguments)] pub async fn create_equality_proof_context_state_for_transfer<S: Signer>( @@ -2854,7 +2750,7 @@ where source_account: &Pubkey, destination_account: &Pubkey, source_authority: &Pubkey, - proof_account: Option<&ProofAccount>, + context_state_account: Option<&Pubkey>, transfer_amount: u64, account_info: Option<TransferAccountInfo>, source_elgamal_keypair: &ElGamalKeypair, @@ -2878,7 +2774,7 @@ where TransferAccountInfo::new(confidential_transfer_account) }; - let proof_data = if proof_account.is_some() { + let proof_data = if context_state_account.is_some() { None } else { Some( @@ -2897,11 +2793,12 @@ where ) }; - // cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`, - // which is guaranteed by the previous check - let proof_location = - Self::confidential_transfer_create_proof_location(proof_data.as_ref(), proof_account) - .unwrap(); + let proof_location = if let Some(proof_data_temp) = proof_data.as_ref() { + ProofLocation::InstructionOffset(1.try_into().unwrap(), proof_data_temp) + } else { + let context_state_account = context_state_account.unwrap(); + ProofLocation::ContextStateAccount(context_state_account) + }; let new_decryptable_available_balance = account_info .new_decryptable_available_balance(transfer_amount, source_aes_key) @@ -3596,7 +3493,7 @@ where &self, destination_account: &Pubkey, withdraw_withheld_authority: &Pubkey, - proof_account: Option<&ProofAccount>, + context_state_account: Option<&Pubkey>, withheld_tokens_info: Option<WithheldTokensInfo>, withdraw_withheld_authority_elgamal_keypair: &ElGamalKeypair, destination_elgamal_pubkey: &ElGamalPubkey, @@ -3616,7 +3513,7 @@ where WithheldTokensInfo::new(&confidential_transfer_fee_config.withheld_amount) }; - let proof_data = if proof_account.is_some() { + let proof_data = if context_state_account.is_some() { None } else { Some( @@ -3629,11 +3526,12 @@ where ) }; - // cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`, - // which is guaranteed by the previous check - let proof_location = - Self::confidential_transfer_create_proof_location(proof_data.as_ref(), proof_account) - .unwrap(); + let proof_location = if let Some(proof_data_temp) = proof_data.as_ref() { + ProofLocation::InstructionOffset(1.try_into().unwrap(), proof_data_temp) + } else { + let context_state_account = context_state_account.unwrap(); + ProofLocation::ContextStateAccount(context_state_account) + }; self.process_ixs( &confidential_transfer_fee::instruction::withdraw_withheld_tokens_from_mint( @@ -3656,7 +3554,7 @@ where &self, destination_account: &Pubkey, withdraw_withheld_authority: &Pubkey, - proof_account: Option<&ProofAccount>, + context_state_account: Option<&Pubkey>, withheld_tokens_info: Option<WithheldTokensInfo>, withdraw_withheld_authority_elgamal_keypair: &ElGamalKeypair, destination_elgamal_pubkey: &ElGamalPubkey, @@ -3687,7 +3585,7 @@ where WithheldTokensInfo::new(&aggregate_withheld_amount.into()) }; - let proof_data = if proof_account.is_some() { + let proof_data = if context_state_account.is_some() { None } else { Some( @@ -3700,11 +3598,12 @@ where ) }; - // cannot panic as long as either `proof_data` or `proof_account` is `Some(..)`, - // which is guaranteed by the previous check - let proof_location = - Self::confidential_transfer_create_proof_location(proof_data.as_ref(), proof_account) - .unwrap(); + let proof_location = if let Some(proof_data_temp) = proof_data.as_ref() { + ProofLocation::InstructionOffset(1.try_into().unwrap(), proof_data_temp) + } else { + let context_state_account = context_state_account.unwrap(); + ProofLocation::ContextStateAccount(context_state_account) + }; self.process_ixs( &confidential_transfer_fee::instruction::withdraw_withheld_tokens_from_accounts( @@ -3788,34 +3687,6 @@ where .await } - // Creates `ProofLocation` from proof data and `ProofAccount`. If both - // `proof_data` and `proof_account` are `None`, then the result is `None`. - fn confidential_transfer_create_proof_location<'a, ZK: ZkProofData<U>, U: Pod>( - proof_data: Option<&'a ZK>, - proof_account: Option<&'a ProofAccount>, - ) -> Option<ProofLocation<'a, ZK>> { - if let Some(proof_data) = proof_data { - Some(ProofLocation::InstructionOffset( - 1.try_into().unwrap(), - ProofData::InstructionData(proof_data), - )) - } else if let Some(proof_account) = proof_account { - match proof_account { - ProofAccount::ContextAccount(context_state_account) => { - Some(ProofLocation::ContextStateAccount(context_state_account)) - } - ProofAccount::RecordAccount(record_account, offset) => { - Some(ProofLocation::InstructionOffset( - 1.try_into().unwrap(), - ProofData::RecordAccount(record_account, *offset), - )) - } - } - } else { - None - } - } - pub async fn withdraw_excess_lamports<S: Signers>( &self, source: &Pubkey, @@ -4209,22 +4080,3 @@ where self.process_ixs(&instructions, signing_keypairs).await } } - -/// Calculates the maximum chunk size for a zero-knowledge proof record -/// instruction to fit inside a single transaction. -fn calculate_record_max_chunk_size<F>( - create_record_instructions: F, - first_instruction: bool, -) -> usize -where - F: Fn(bool, &[u8], u64) -> Vec<Instruction>, -{ - let ixs = create_record_instructions(first_instruction, &[], 0); - let message = Message::new_with_blockhash(&ixs, Some(&Pubkey::default()), &Hash::default()); - let tx_size = bincode::serialized_size(&Transaction { - signatures: vec![Signature::default(); message.header.num_required_signatures as usize], - message, - }) - .unwrap() as usize; - PACKET_DATA_SIZE.saturating_sub(tx_size).saturating_sub(1) -} diff --git a/token/program-2022-test/Cargo.toml b/token/program-2022-test/Cargo.toml index bb9ec0caed8..6350ebd285a 100644 --- a/token/program-2022-test/Cargo.toml +++ b/token/program-2022-test/Cargo.toml @@ -27,9 +27,6 @@ spl-memo = { version = "5.0.0", path = "../../memo/program", features = [ "no-entrypoint", ] } spl-pod = { version = "0.3.0", path = "../../libraries/pod" } -spl-record = { version = "0.2.0", path = "../../record/program", features = [ - "no-entrypoint", -]} spl-token-2022 = { version = "4.0.0", path = "../program-2022", features = [ "no-entrypoint", ] } diff --git a/token/program-2022-test/tests/confidential_transfer.rs b/token/program-2022-test/tests/confidential_transfer.rs index ce125d5e029..bacc44c2848 100644 --- a/token/program-2022-test/tests/confidential_transfer.rs +++ b/token/program-2022-test/tests/confidential_transfer.rs @@ -15,13 +15,12 @@ use { transaction::{Transaction, TransactionError}, transport::TransportError, }, - spl_record::state::RecordData, spl_token_2022::{ error::TokenError, extension::{ confidential_transfer::{ self, - account_info::{EmptyAccountAccountInfo, TransferAccountInfo, WithdrawAccountInfo}, + account_info::TransferAccountInfo, instruction::{ CloseSplitContextStateAccounts, TransferSplitContextStateAccounts, TransferWithFeeSplitContextStateAccounts, @@ -39,7 +38,7 @@ use { }, }, spl_token_client::{ - proof_generation::{transfer_with_fee_split_proof_data, ProofAccount}, + proof_generation::transfer_with_fee_split_proof_data, token::{ComputeUnitLimit, ExtensionInitializationParams, TokenError as TokenClientError}, }, std::{convert::TryInto, mem::size_of}, @@ -446,86 +445,6 @@ async fn confidential_transfer_empty_account() { .unwrap(); } -#[tokio::test] -async fn confidential_transfer_empty_account_with_record() { - let authority = Keypair::new(); - let auto_approve_new_accounts = true; - let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); - - let mut context = TestContext::new().await; - - // newly created confidential transfer account should hold no balance and - // therefore, immediately closable - context - .init_token_with_mint(vec![ - ExtensionInitializationParams::ConfidentialTransferMint { - authority: Some(authority.pubkey()), - auto_approve_new_accounts, - auditor_elgamal_pubkey: Some(auditor_elgamal_pubkey), - }, - ]) - .await - .unwrap(); - - let TokenContext { token, alice, .. } = context.token_context.unwrap(); - let alice_meta = ConfidentialTokenAccountMeta::new(&token, &alice, None, false, false).await; - - let state = token - .get_account_info(&alice_meta.token_account) - .await - .unwrap(); - let extension = state - .get_extension::<ConfidentialTransferAccount>() - .unwrap(); - let account_info = EmptyAccountAccountInfo::new(extension); - - let zero_balance_proof = account_info - .generate_proof_data(&alice_meta.elgamal_keypair) - .unwrap(); - - let record_account = Keypair::new(); - let record_account_authority = Keypair::new(); - - token - .confidential_transfer_create_record_account( - &record_account.pubkey(), - &record_account_authority.pubkey(), - &zero_balance_proof, - &record_account, - &record_account_authority, - ) - .await - .unwrap(); - - let proof_account = ProofAccount::RecordAccount( - record_account.pubkey(), - RecordData::WRITABLE_START_INDEX as u32, - ); - - token - .confidential_transfer_empty_account( - &alice_meta.token_account, - &alice.pubkey(), - Some(&proof_account), - None, - &alice_meta.elgamal_keypair, - &[&alice], - ) - .await - .unwrap(); - - token - .confidential_transfer_close_record_account( - &record_account.pubkey(), - &record_account_authority.pubkey(), - &alice.pubkey(), - &record_account_authority, - ) - .await - .unwrap(); -} - #[cfg(feature = "zk-ops")] #[tokio::test] async fn confidential_transfer_deposit() { @@ -890,137 +809,6 @@ async fn confidential_transfer_withdraw() { .unwrap(); } -#[cfg(feature = "zk-ops")] -#[tokio::test] -async fn confidential_transfer_withdraw_with_record_account() { - let authority = Keypair::new(); - let auto_approve_new_accounts = true; - let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); - - let mut context = TestContext::new().await; - context - .init_token_with_mint(vec![ - ExtensionInitializationParams::ConfidentialTransferMint { - authority: Some(authority.pubkey()), - auto_approve_new_accounts, - auditor_elgamal_pubkey: Some(auditor_elgamal_pubkey), - }, - ]) - .await - .unwrap(); - - let TokenContext { - token, - alice, - mint_authority, - decimals, - .. - } = context.token_context.unwrap(); - let alice_meta = ConfidentialTokenAccountMeta::new_with_tokens( - &token, - &alice, - None, - false, - false, - &mint_authority, - 42, - decimals, - ) - .await; - - let state = token - .get_account_info(&alice_meta.token_account) - .await - .unwrap(); - assert_eq!(state.base.amount, 0); - alice_meta - .check_balances( - &token, - ConfidentialTokenAccountBalances { - pending_balance_lo: 0, - pending_balance_hi: 0, - available_balance: 42, - decryptable_available_balance: 42, - }, - ) - .await; - - let state = token - .get_account_info(&alice_meta.token_account) - .await - .unwrap(); - let extension = state - .get_extension::<ConfidentialTransferAccount>() - .unwrap(); - let account_info = WithdrawAccountInfo::new(extension); - - let withdraw_proof = account_info - .generate_proof_data(42, &alice_meta.elgamal_keypair, &alice_meta.aes_key) - .unwrap(); - - let record_account = Keypair::new(); - let record_account_authority = Keypair::new(); - - token - .confidential_transfer_create_record_account( - &record_account.pubkey(), - &record_account_authority.pubkey(), - &withdraw_proof, - &record_account, - &record_account_authority, - ) - .await - .unwrap(); - - let proof_account = ProofAccount::RecordAccount( - record_account.pubkey(), - RecordData::WRITABLE_START_INDEX as u32, - ); - - token - .confidential_transfer_withdraw( - &alice_meta.token_account, - &alice.pubkey(), - Some(&proof_account), - 42, - decimals, - None, - &alice_meta.elgamal_keypair, - &alice_meta.aes_key, - &[&alice], - ) - .await - .unwrap(); - - let state = token - .get_account_info(&alice_meta.token_account) - .await - .unwrap(); - assert_eq!(state.base.amount, 42); - alice_meta - .check_balances( - &token, - ConfidentialTokenAccountBalances { - pending_balance_lo: 0, - pending_balance_hi: 0, - available_balance: 0, - decryptable_available_balance: 0, - }, - ) - .await; - - token - .confidential_transfer_close_record_account( - &record_account.pubkey(), - &record_account_authority.pubkey(), - &alice.pubkey(), - &record_account_authority, - ) - .await - .unwrap(); -} - #[cfg(feature = "zk-ops")] #[tokio::test] async fn confidential_transfer_transfer() { @@ -1847,9 +1635,7 @@ async fn confidential_transfer_configure_token_account_with_proof_context() { .confidential_transfer_configure_token_account( &token_account, &alice.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), None, &elgamal_keypair, &aes_key, @@ -1936,9 +1722,7 @@ async fn confidential_transfer_configure_token_account_with_proof_context() { .confidential_transfer_configure_token_account( &token_account, &bob.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), None, &elgamal_keypair, &aes_key, @@ -2025,9 +1809,7 @@ async fn confidential_transfer_empty_account_with_proof_context() { .confidential_transfer_empty_account( &alice_meta.token_account, &alice.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), None, &alice_meta.elgamal_keypair, &[&alice], @@ -2082,9 +1864,7 @@ async fn confidential_transfer_empty_account_with_proof_context() { .confidential_transfer_empty_account( &bob_meta.token_account, &bob.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), None, &bob_meta.elgamal_keypair, &[&bob], @@ -2197,9 +1977,7 @@ async fn confidential_transfer_withdraw_with_proof_context() { .confidential_transfer_withdraw( &alice_meta.token_account, &alice.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), 0, decimals, None, @@ -2257,9 +2035,7 @@ async fn confidential_transfer_withdraw_with_proof_context() { .confidential_transfer_withdraw( &bob_meta.token_account, &bob.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), 0, decimals, None, @@ -2393,9 +2169,7 @@ async fn confidential_transfer_transfer_with_proof_context() { &alice_meta.token_account, &bob_meta.token_account, &alice.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), 42, None, &alice_meta.elgamal_keypair, @@ -2467,9 +2241,7 @@ async fn confidential_transfer_transfer_with_proof_context() { &alice_meta.token_account, &bob_meta.token_account, &alice.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), 0, None, &alice_meta.elgamal_keypair, diff --git a/token/program-2022-test/tests/confidential_transfer_fee.rs b/token/program-2022-test/tests/confidential_transfer_fee.rs index 1221c773828..161ee2c2a81 100644 --- a/token/program-2022-test/tests/confidential_transfer_fee.rs +++ b/token/program-2022-test/tests/confidential_transfer_fee.rs @@ -13,7 +13,6 @@ use { transaction::{Transaction, TransactionError}, transport::TransportError, }, - spl_record::state::RecordData, spl_token_2022::{ error::TokenError, extension::{ @@ -36,7 +35,6 @@ use { }, spl_token_client::{ client::{SendTransaction, SimulateTransaction}, - proof_generation::ProofAccount, token::{ExtensionInitializationParams, Token, TokenError as TokenClientError}, }, std::{convert::TryInto, mem::size_of}, @@ -614,168 +612,6 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_mint() { check_withheld_amount_in_mint(&token, &withdraw_withheld_authority_elgamal_keypair, 0).await; } -#[cfg(feature = "zk-ops")] -#[tokio::test] -async fn confidential_transfer_withdraw_withheld_tokens_from_mint_with_record_account() { - let transfer_fee_authority = Keypair::new(); - let withdraw_withheld_authority = Keypair::new(); - - let confidential_transfer_authority = Keypair::new(); - let auto_approve_new_accounts = true; - let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); - - let confidential_transfer_fee_authority = Keypair::new(); - let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); - let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); - - let mut context = TestContext::new().await; - context - .init_token_with_mint(vec![ - ExtensionInitializationParams::TransferFeeConfig { - transfer_fee_config_authority: Some(transfer_fee_authority.pubkey()), - withdraw_withheld_authority: Some(withdraw_withheld_authority.pubkey()), - transfer_fee_basis_points: TEST_FEE_BASIS_POINTS, - maximum_fee: TEST_MAXIMUM_FEE, - }, - ExtensionInitializationParams::ConfidentialTransferMint { - authority: Some(confidential_transfer_authority.pubkey()), - auto_approve_new_accounts, - auditor_elgamal_pubkey: Some(auditor_elgamal_pubkey), - }, - ExtensionInitializationParams::ConfidentialTransferFeeConfig { - authority: Some(confidential_transfer_fee_authority.pubkey()), - withdraw_withheld_authority_elgamal_pubkey, - }, - ]) - .await - .unwrap(); - - let TokenContext { - token, - alice, - bob, - mint_authority, - decimals, - .. - } = context.token_context.unwrap(); - - let alice_meta = - ConfidentialTokenAccountMeta::new(&token, &alice, &mint_authority, 100, decimals).await; - let bob_meta = - ConfidentialTokenAccountMeta::new(&token, &bob, &mint_authority, 0, decimals).await; - - let transfer_fee_parameters = TransferFee { - epoch: 0.into(), - maximum_fee: TEST_MAXIMUM_FEE.into(), - transfer_fee_basis_points: TEST_FEE_BASIS_POINTS.into(), - }; - - // Test fee is 2.5% so the withheld fees should be 3 - token - .confidential_transfer_transfer_with_fee( - &alice_meta.token_account, - &bob_meta.token_account, - &alice.pubkey(), - None, - 100, - None, - &alice_meta.elgamal_keypair, - &alice_meta.aes_key, - bob_meta.elgamal_keypair.pubkey(), - Some(auditor_elgamal_keypair.pubkey()), - withdraw_withheld_authority_elgamal_keypair.pubkey(), - transfer_fee_parameters.transfer_fee_basis_points.into(), - transfer_fee_parameters.maximum_fee.into(), - &[&alice], - ) - .await - .unwrap(); - - token - .confidential_transfer_harvest_withheld_tokens_to_mint(&[&bob_meta.token_account]) - .await - .unwrap(); - - let state = token - .get_account_info(&bob_meta.token_account) - .await - .unwrap(); - let extension = state - .get_extension::<ConfidentialTransferFeeAmount>() - .unwrap(); - assert_eq!(extension.withheld_amount, pod::ElGamalCiphertext::zeroed()); - - // calculate and encrypt fee to attach to the `WithdrawWithheldTokensFromMint` - // instruction data - let fee = transfer_fee_parameters.calculate_fee(100).unwrap(); - let new_decryptable_available_balance = alice_meta.aes_key.encrypt(fee); - - check_withheld_amount_in_mint(&token, &withdraw_withheld_authority_elgamal_keypair, fee).await; - - let state = token.get_mint_info().await.unwrap(); - let extension = state - .get_extension::<ConfidentialTransferFeeConfig>() - .unwrap(); - let account_info = WithheldTokensInfo::new(&extension.withheld_amount); - - let equality_proof = account_info - .generate_proof_data( - &withdraw_withheld_authority_elgamal_keypair, - alice_meta.elgamal_keypair.pubkey(), - ) - .unwrap(); - - let record_account = Keypair::new(); - let record_account_authority = Keypair::new(); - - token - .confidential_transfer_create_record_account( - &record_account.pubkey(), - &record_account_authority.pubkey(), - &equality_proof, - &record_account, - &record_account_authority, - ) - .await - .unwrap(); - - let proof_account = ProofAccount::RecordAccount( - record_account.pubkey(), - RecordData::WRITABLE_START_INDEX as u32, - ); - - token - .confidential_transfer_withdraw_withheld_tokens_from_mint( - &alice_meta.token_account, - &withdraw_withheld_authority.pubkey(), - Some(&proof_account), - None, - &withdraw_withheld_authority_elgamal_keypair, - alice_meta.elgamal_keypair.pubkey(), - &new_decryptable_available_balance.into(), - &[&withdraw_withheld_authority], - ) - .await - .unwrap(); - - // withheld fees are withdrawn back to alice's account - alice_meta - .check_balances( - &token, - ConfidentialTokenAccountBalances { - pending_balance_lo: 0, - pending_balance_hi: 0, - available_balance: 3, - decryptable_available_balance: 3, - }, - ) - .await; - - check_withheld_amount_in_mint(&token, &withdraw_withheld_authority_elgamal_keypair, 0).await; -} - #[cfg(feature = "zk-ops")] #[tokio::test] async fn confidential_transfer_withdraw_withheld_tokens_from_accounts() { @@ -906,172 +742,6 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_accounts() { assert_eq!(extension.withheld_amount, pod::ElGamalCiphertext::zeroed()); } -#[cfg(feature = "zk-ops")] -#[tokio::test] -async fn confidential_transfer_withdraw_withheld_tokens_from_accounts_with_record_account() { - let transfer_fee_authority = Keypair::new(); - let withdraw_withheld_authority = Keypair::new(); - - let confidential_transfer_authority = Keypair::new(); - let auto_approve_new_accounts = true; - let auditor_elgamal_keypair = ElGamalKeypair::new_rand(); - let auditor_elgamal_pubkey = (*auditor_elgamal_keypair.pubkey()).into(); - - let confidential_transfer_fee_authority = Keypair::new(); - let withdraw_withheld_authority_elgamal_keypair = ElGamalKeypair::new_rand(); - let withdraw_withheld_authority_elgamal_pubkey = - (*withdraw_withheld_authority_elgamal_keypair.pubkey()).into(); - - let mut context = TestContext::new().await; - context - .init_token_with_mint(vec![ - ExtensionInitializationParams::TransferFeeConfig { - transfer_fee_config_authority: Some(transfer_fee_authority.pubkey()), - withdraw_withheld_authority: Some(withdraw_withheld_authority.pubkey()), - transfer_fee_basis_points: TEST_FEE_BASIS_POINTS, - maximum_fee: TEST_MAXIMUM_FEE, - }, - ExtensionInitializationParams::ConfidentialTransferMint { - authority: Some(confidential_transfer_authority.pubkey()), - auto_approve_new_accounts, - auditor_elgamal_pubkey: Some(auditor_elgamal_pubkey), - }, - ExtensionInitializationParams::ConfidentialTransferFeeConfig { - authority: Some(confidential_transfer_fee_authority.pubkey()), - withdraw_withheld_authority_elgamal_pubkey, - }, - ]) - .await - .unwrap(); - - let TokenContext { - token, - alice, - bob, - mint_authority, - decimals, - .. - } = context.token_context.unwrap(); - - let alice_meta = - ConfidentialTokenAccountMeta::new(&token, &alice, &mint_authority, 100, decimals).await; - let bob_meta = - ConfidentialTokenAccountMeta::new(&token, &bob, &mint_authority, 0, decimals).await; - - let transfer_fee_parameters = TransferFee { - epoch: 0.into(), - maximum_fee: TEST_MAXIMUM_FEE.into(), - transfer_fee_basis_points: TEST_FEE_BASIS_POINTS.into(), - }; - - // Test fee is 2.5% so the withheld fees should be 3 - token - .confidential_transfer_transfer_with_fee( - &alice_meta.token_account, - &bob_meta.token_account, - &alice.pubkey(), - None, - 100, - None, - &alice_meta.elgamal_keypair, - &alice_meta.aes_key, - bob_meta.elgamal_keypair.pubkey(), - Some(auditor_elgamal_keypair.pubkey()), - withdraw_withheld_authority_elgamal_keypair.pubkey(), - transfer_fee_parameters.transfer_fee_basis_points.into(), - transfer_fee_parameters.maximum_fee.into(), - &[&alice], - ) - .await - .unwrap(); - - let state = token - .get_account_info(&bob_meta.token_account) - .await - .unwrap(); - let withheld_amount = state - .get_extension::<ConfidentialTransferFeeAmount>() - .unwrap() - .withheld_amount; - let withheld_tokens_info = WithheldTokensInfo::new(&withheld_amount); - - let equality_proof = withheld_tokens_info - .generate_proof_data( - &withdraw_withheld_authority_elgamal_keypair, - alice_meta.elgamal_keypair.pubkey(), - ) - .unwrap(); - - let record_account = Keypair::new(); - let record_account_authority = Keypair::new(); - - token - .confidential_transfer_create_record_account( - &record_account.pubkey(), - &record_account_authority.pubkey(), - &equality_proof, - &record_account, - &record_account_authority, - ) - .await - .unwrap(); - - let proof_account = ProofAccount::RecordAccount( - record_account.pubkey(), - RecordData::WRITABLE_START_INDEX as u32, - ); - - let fee = transfer_fee_parameters.calculate_fee(100).unwrap(); - let new_decryptable_available_balance = alice_meta.aes_key.encrypt(fee); - token - .confidential_transfer_withdraw_withheld_tokens_from_accounts( - &alice_meta.token_account, - &withdraw_withheld_authority.pubkey(), - Some(&proof_account), - None, - &withdraw_withheld_authority_elgamal_keypair, - alice_meta.elgamal_keypair.pubkey(), - &new_decryptable_available_balance.into(), - &[&bob_meta.token_account], - &[&withdraw_withheld_authority], - ) - .await - .unwrap(); - - alice_meta - .check_balances( - &token, - ConfidentialTokenAccountBalances { - pending_balance_lo: 0, - pending_balance_hi: 0, - available_balance: fee, - decryptable_available_balance: fee, - }, - ) - .await; - - bob_meta - .check_balances( - &token, - ConfidentialTokenAccountBalances { - pending_balance_lo: 97, - pending_balance_hi: 0, - available_balance: 0, - decryptable_available_balance: 0, - }, - ) - .await; - - let state = token - .get_account_info(&bob_meta.token_account) - .await - .unwrap(); - let extension = state - .get_extension::<ConfidentialTransferFeeAmount>() - .unwrap(); - assert_eq!(extension.withheld_amount, pod::ElGamalCiphertext::zeroed()); -} - #[cfg(feature = "zk-ops")] #[tokio::test] async fn confidential_transfer_withdraw_withheld_tokens_from_mint_with_proof_context() { @@ -1215,9 +885,7 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_mint_with_proof_con .confidential_transfer_withdraw_withheld_tokens_from_mint( &alice_meta.token_account, &withdraw_withheld_authority.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), None, &withdraw_withheld_authority_elgamal_keypair, alice_meta.elgamal_keypair.pubkey(), @@ -1383,9 +1051,7 @@ async fn confidential_transfer_withdraw_withheld_tokens_from_accounts_with_proof .confidential_transfer_withdraw_withheld_tokens_from_accounts( &alice_meta.token_account, &withdraw_withheld_authority.pubkey(), - Some(&ProofAccount::ContextAccount( - context_state_account.pubkey(), - )), + Some(&context_state_account.pubkey()), None, &withdraw_withheld_authority_elgamal_keypair, alice_meta.elgamal_keypair.pubkey(), diff --git a/token/program-2022-test/tests/program_test.rs b/token/program-2022-test/tests/program_test.rs index 25fd28abd79..0d4979383b4 100644 --- a/token/program-2022-test/tests/program_test.rs +++ b/token/program-2022-test/tests/program_test.rs @@ -42,14 +42,7 @@ pub struct TestContext { impl TestContext { pub async fn new() -> Self { - let mut program_test = - ProgramTest::new("spl_token_2022", id(), processor!(Processor::process)); - program_test.prefer_bpf(false); - program_test.add_program( - "spl_record", - spl_record::id(), - processor!(spl_record::processor::process_instruction), - ); + let program_test = ProgramTest::new("spl_token_2022", id(), processor!(Processor::process)); let context = program_test.start_with_context().await; let context = Arc::new(Mutex::new(context)); diff --git a/token/program-2022/src/extension/confidential_transfer/instruction.rs b/token/program-2022/src/extension/confidential_transfer/instruction.rs index d8e857c3817..ac73574f5a9 100644 --- a/token/program-2022/src/extension/confidential_transfer/instruction.rs +++ b/token/program-2022/src/extension/confidential_transfer/instruction.rs @@ -13,7 +13,7 @@ use { check_program_account, extension::confidential_transfer::{ciphertext_extraction::SourceDecryptHandles, *}, instruction::{encode_instruction, TokenInstruction}, - proof::{ProofData, ProofLocation}, + proof::ProofLocation, }, bytemuck::Zeroable, // `Pod` comes from zk_token_proof_instruction num_enum::{IntoPrimitive, TryFromPrimitive}, @@ -90,9 +90,7 @@ pub enum ConfidentialTransferInstruction { /// in the same transaction or context state account if /// `VerifyPubkeyValidityProof` is pre-verified into a context state /// account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[signer]` The single source account owner. + /// 3. `[signer]` The single source account owner. /// /// * Multisignature owner/delegate /// 0. `[writeable]` The SPL Token account. @@ -101,10 +99,8 @@ pub enum ConfidentialTransferInstruction { /// in the same transaction or context state account if /// `VerifyPubkeyValidityProof` is pre-verified into a context state /// account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[]` The multisig source account owner. - /// 5.. `[signer]` Required M signer accounts for the SPL Token Multisig + /// 3. `[]` The multisig source account owner. + /// 4.. `[signer]` Required M signer accounts for the SPL Token Multisig /// account. /// /// Data expected by this instruction: @@ -155,9 +151,7 @@ pub enum ConfidentialTransferInstruction { /// the same transaction or context state account if /// `VerifyZeroBalanceProof` is pre-verified into a context state /// account. - /// 2. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 3. `[signer]` The single account owner. + /// 2. `[signer]` The single account owner. /// /// * Multisignature owner/delegate /// 0. `[writable]` The SPL Token account. @@ -165,10 +159,8 @@ pub enum ConfidentialTransferInstruction { /// the same transaction or context state account if /// `VerifyZeroBalanceProof` is pre-verified into a context state /// account. - /// 2. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 3. `[]` The multisig account owner. - /// 4.. `[signer]` Required M signer accounts for the SPL Token Multisig + /// 2. `[]` The multisig account owner. + /// 3.. `[signer]` Required M signer accounts for the SPL Token Multisig /// account. /// /// Data expected by this instruction: @@ -222,9 +214,7 @@ pub enum ConfidentialTransferInstruction { /// 2. `[]` Instructions sysvar if `VerifyWithdraw` is included in the /// same transaction or context state account if `VerifyWithdraw` is /// pre-verified into a context state account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[signer]` The single source account owner. + /// 3. `[signer]` The single source account owner. /// /// * Multisignature owner/delegate /// 0. `[writable]` The SPL Token account. @@ -232,10 +222,8 @@ pub enum ConfidentialTransferInstruction { /// 2. `[]` Instructions sysvar if `VerifyWithdraw` is included in the /// same transaction or context state account if `VerifyWithdraw` is /// pre-verified into a context state account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[]` The multisig source account owner. - /// 5.. `[signer]` Required M signer accounts for the SPL Token Multisig + /// 3. `[]` The multisig source account owner. + /// 4.. `[signer]` Required M signer accounts for the SPL Token Multisig /// account. /// /// Data expected by this instruction: @@ -260,9 +248,7 @@ pub enum ConfidentialTransferInstruction { /// `VerifyTransferWithFee` is included in the same transaction or /// context state account if these proofs are pre-verified into a /// context state account. - /// 5. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 6. `[signer]` The single source account owner. + /// 5. `[signer]` The single source account owner. /// /// * Multisignature owner/delegate /// 1. `[writable]` The source SPL Token account. @@ -272,10 +258,8 @@ pub enum ConfidentialTransferInstruction { /// `VerifyTransferWithFee` is included in the same transaction or /// context state account if these proofs are pre-verified into a /// context state account. - /// 5. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 6. `[]` The multisig source account owner. - /// 7.. `[signer]` Required M signer accounts for the SPL Token Multisig + /// 5. `[]` The multisig source account owner. + /// 6.. `[signer]` Required M signer accounts for the SPL Token Multisig /// account. /// /// Data expected by this instruction: @@ -731,11 +715,8 @@ pub fn inner_configure_account( ]; let proof_instruction_offset = match proof_data_location { - ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => { + ProofLocation::InstructionOffset(proof_instruction_offset, _) => { accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false)); - if let ProofData::RecordAccount(record_address, _) = proof_data { - accounts.push(AccountMeta::new_readonly(*record_address, false)); - } proof_instruction_offset.into() } ProofLocation::ContextStateAccount(context_state_account) => { @@ -800,16 +781,8 @@ pub fn configure_account( if proof_instruction_offset != 1 { return Err(TokenError::InvalidProofInstructionOffset.into()); } - match proof_data { - ProofData::InstructionData(data) => { - instructions.push(verify_pubkey_validity(None, data)) - } - ProofData::RecordAccount(address, offset) => instructions.push( - ProofInstruction::VerifyPubkeyValidity - .encode_verify_proof_from_account(None, address, offset), - ), - }; - } + instructions.push(verify_pubkey_validity(None, proof_data)); + }; Ok(instructions) } @@ -854,11 +827,8 @@ pub fn inner_empty_account( let mut accounts = vec![AccountMeta::new(*token_account, false)]; let proof_instruction_offset = match proof_data_location { - ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => { + ProofLocation::InstructionOffset(proof_instruction_offset, _) => { accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false)); - if let ProofData::RecordAccount(record_address, _) = proof_data { - accounts.push(AccountMeta::new_readonly(*record_address, false)); - } proof_instruction_offset.into() } ProofLocation::ContextStateAccount(context_state_account) => { @@ -914,13 +884,7 @@ pub fn empty_account( if proof_instruction_offset != 1 { return Err(TokenError::InvalidProofInstructionOffset.into()); } - match proof_data { - ProofData::InstructionData(data) => instructions.push(verify_zero_balance(None, data)), - ProofData::RecordAccount(address, offset) => instructions.push( - ProofInstruction::VerifyZeroBalance - .encode_verify_proof_from_account(None, address, offset), - ), - }; + instructions.push(verify_zero_balance(None, proof_data)); }; Ok(instructions) @@ -982,11 +946,8 @@ pub fn inner_withdraw( ]; let proof_instruction_offset = match proof_data_location { - ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => { + ProofLocation::InstructionOffset(proof_instruction_offset, _) => { accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false)); - if let ProofData::RecordAccount(record_address, _) = proof_data { - accounts.push(AccountMeta::new_readonly(*record_address, false)); - } proof_instruction_offset.into() } ProofLocation::ContextStateAccount(context_state_account) => { @@ -1054,13 +1015,7 @@ pub fn withdraw( if proof_instruction_offset != 1 { return Err(TokenError::InvalidProofInstructionOffset.into()); } - match proof_data { - ProofData::InstructionData(data) => instructions.push(verify_withdraw(None, data)), - ProofData::RecordAccount(address, offset) => instructions.push( - ProofInstruction::VerifyWithdraw - .encode_verify_proof_from_account(None, address, offset), - ), - }; + instructions.push(verify_withdraw(None, proof_data)); }; Ok(instructions) @@ -1088,11 +1043,8 @@ pub fn inner_transfer( ]; let proof_instruction_offset = match proof_data_location { - ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => { + ProofLocation::InstructionOffset(proof_instruction_offset, _) => { accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false)); - if let ProofData::RecordAccount(record_address, _) = proof_data { - accounts.push(AccountMeta::new_readonly(*record_address, false)); - } proof_instruction_offset.into() } ProofLocation::ContextStateAccount(context_state_account) => { @@ -1156,13 +1108,7 @@ pub fn transfer( if proof_instruction_offset != 1 { return Err(TokenError::InvalidProofInstructionOffset.into()); } - match proof_data { - ProofData::InstructionData(data) => instructions.push(verify_transfer(None, data)), - ProofData::RecordAccount(address, offset) => instructions.push( - ProofInstruction::VerifyTransfer - .encode_verify_proof_from_account(None, address, offset), - ), - }; + instructions.push(verify_transfer(None, proof_data)); }; Ok(instructions) @@ -1190,11 +1136,8 @@ pub fn inner_transfer_with_fee( ]; let proof_instruction_offset = match proof_data_location { - ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => { + ProofLocation::InstructionOffset(proof_instruction_offset, _) => { accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false)); - if let ProofData::RecordAccount(record_address, _) = proof_data { - accounts.push(AccountMeta::new_readonly(*record_address, false)); - } proof_instruction_offset.into() } ProofLocation::ContextStateAccount(context_state_account) => { @@ -1258,15 +1201,7 @@ pub fn transfer_with_fee( if proof_instruction_offset != 1 { return Err(TokenError::InvalidProofInstructionOffset.into()); } - match proof_data { - ProofData::InstructionData(data) => { - instructions.push(verify_transfer_with_fee(None, data)) - } - ProofData::RecordAccount(address, offset) => instructions.push( - ProofInstruction::VerifyTransferWithFee - .encode_verify_proof_from_account(None, address, offset), - ), - }; + instructions.push(verify_transfer_with_fee(None, proof_data)); }; Ok(instructions) diff --git a/token/program-2022/src/extension/confidential_transfer/verify_proof.rs b/token/program-2022/src/extension/confidential_transfer/verify_proof.rs index dc234d65bff..13c6001ba7b 100644 --- a/token/program-2022/src/extension/confidential_transfer/verify_proof.rs +++ b/token/program-2022/src/extension/confidential_transfer/verify_proof.rs @@ -43,13 +43,11 @@ pub fn verify_configure_account_proof( let sysvar_account_info = next_account_info(account_info_iter)?; let zkp_instruction = get_instruction_relative(proof_instruction_offset, sysvar_account_info)?; - Ok(decode_proof_instruction_context::< + Ok(*decode_proof_instruction_context::< PubkeyValidityData, PubkeyValidityProofContext, >( - account_info_iter, - ProofInstruction::VerifyPubkeyValidity, - &zkp_instruction, + ProofInstruction::VerifyPubkeyValidity, &zkp_instruction )?) } } @@ -79,13 +77,11 @@ pub fn verify_empty_account_proof( let sysvar_account_info = next_account_info(account_info_iter)?; let zkp_instruction = get_instruction_relative(proof_instruction_offset, sysvar_account_info)?; - Ok(decode_proof_instruction_context::< + Ok(*decode_proof_instruction_context::< ZeroBalanceProofData, ZeroBalanceProofContext, >( - account_info_iter, - ProofInstruction::VerifyZeroBalance, - &zkp_instruction, + ProofInstruction::VerifyZeroBalance, &zkp_instruction )?) } } @@ -114,13 +110,11 @@ pub fn verify_withdraw_proof( let sysvar_account_info = next_account_info(account_info_iter)?; let zkp_instruction = get_instruction_relative(proof_instruction_offset, sysvar_account_info)?; - Ok(decode_proof_instruction_context::< + Ok(*decode_proof_instruction_context::< WithdrawData, WithdrawProofContext, >( - account_info_iter, - ProofInstruction::VerifyWithdraw, - &zkp_instruction, + ProofInstruction::VerifyWithdraw, &zkp_instruction )?) } } @@ -265,13 +259,11 @@ pub fn verify_transfer_proof( let sysvar_account_info = next_account_info(account_info_iter)?; let zkp_instruction = get_instruction_relative(proof_instruction_offset, sysvar_account_info)?; - let proof_context = - (decode_proof_instruction_context::<TransferData, TransferProofContext>( - account_info_iter, - ProofInstruction::VerifyTransfer, - &zkp_instruction, - )?) - .into(); + let proof_context = (*decode_proof_instruction_context::< + TransferData, + TransferProofContext, + >(ProofInstruction::VerifyTransfer, &zkp_instruction)?) + .into(); Ok(Some(proof_context)) } @@ -498,12 +490,10 @@ pub fn verify_transfer_with_fee_proof( let sysvar_account_info = next_account_info(account_info_iter)?; let zkp_instruction = get_instruction_relative(proof_instruction_offset, sysvar_account_info)?; - let proof_context = - decode_proof_instruction_context::<TransferWithFeeData, TransferWithFeeProofContext>( - account_info_iter, - ProofInstruction::VerifyTransferWithFee, - &zkp_instruction, - )?; + let proof_context = decode_proof_instruction_context::< + TransferWithFeeData, + TransferWithFeeProofContext, + >(ProofInstruction::VerifyTransferWithFee, &zkp_instruction)?; let proof_tranfer_fee_basis_points: u16 = proof_context.fee_parameters.fee_rate_basis_points.into(); @@ -519,7 +509,7 @@ pub fn verify_transfer_with_fee_proof( return Err(TokenError::FeeParametersMismatch.into()); } - Ok(Some(proof_context.into())) + Ok(Some((*proof_context).into())) } } diff --git a/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs b/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs index 9bad6aec922..12a708624cb 100644 --- a/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs +++ b/token/program-2022/src/extension/confidential_transfer_fee/instruction.rs @@ -14,10 +14,8 @@ use { DecryptableBalance, }, instruction::{encode_instruction, TokenInstruction}, - proof::{ProofData, ProofLocation}, - solana_zk_token_sdk::{ - zk_token_elgamal::pod::ElGamalPubkey, zk_token_proof_instruction::ProofInstruction, - }, + proof::ProofLocation, + solana_zk_token_sdk::zk_token_elgamal::pod::ElGamalPubkey, }, bytemuck::{Pod, Zeroable}, num_enum::{IntoPrimitive, TryFromPrimitive}, @@ -77,9 +75,7 @@ pub enum ConfidentialTransferFeeInstruction { /// included in the same transaction or context state account if /// `VerifyCiphertextCiphertextEquality` is pre-verified into a context /// state account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[signer]` The mint's `withdraw_withheld_authority`. + /// 3. `[signer]` The mint's `withdraw_withheld_authority`. /// /// * Multisignature owner/delegate /// 0. `[writable]` The token mint. Must include the `TransferFeeConfig` @@ -90,10 +86,8 @@ pub enum ConfidentialTransferFeeInstruction { /// included in the same transaction or context state account if /// `VerifyCiphertextCiphertextEquality` is pre-verified into a context /// state account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[]` The mint's multisig `withdraw_withheld_authority`. - /// 5. ..3+M `[signer]` M signer accounts. + /// 3. `[]` The mint's multisig `withdraw_withheld_authority`. + /// 4. ..3+M `[signer]` M signer accounts. /// /// Data expected by this instruction: /// WithdrawWithheldTokensFromMintData @@ -142,10 +136,8 @@ pub enum ConfidentialTransferFeeInstruction { /// included in the same transaction or context state account if /// `VerifyCiphertextCiphertextEquality` is pre-verified into a context /// state account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[signer]` The mint's `withdraw_withheld_authority`. - /// 5. ..3+N `[writable]` The source accounts to withdraw from. + /// 3. `[signer]` The mint's `withdraw_withheld_authority`. + /// 4. ..3+N `[writable]` The source accounts to withdraw from. /// /// * Multisignature owner/delegate /// 0. `[]` The token mint. Must include the `TransferFeeConfig` @@ -156,11 +148,9 @@ pub enum ConfidentialTransferFeeInstruction { /// included in the same transaction or context state account if /// `VerifyCiphertextCiphertextEquality` is pre-verified into a context /// state account. - /// 3. `[]` (Optional) Record account if the accompanying proof is to be - /// read from a record account. - /// 4. `[]` The mint's multisig `withdraw_withheld_authority`. - /// 5. ..5+M `[signer]` M signer accounts. - /// 5+M+1. ..5+M+N `[writable]` The source accounts to withdraw from. + /// 3. `[]` The mint's multisig `withdraw_withheld_authority`. + /// 4. ..4+M `[signer]` M signer accounts. + /// 4+M+1. ..4+M+N `[writable]` The source accounts to withdraw from. /// /// Data expected by this instruction: /// WithdrawWithheldTokensFromAccountsData @@ -313,11 +303,8 @@ pub fn inner_withdraw_withheld_tokens_from_mint( ]; let proof_instruction_offset = match proof_data_location { - ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => { + ProofLocation::InstructionOffset(proof_instruction_offset, _) => { accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false)); - if let ProofData::RecordAccount(record_address, _) = proof_data { - accounts.push(AccountMeta::new_readonly(*record_address, false)); - } proof_instruction_offset.into() } ProofLocation::ContextStateAccount(context_state_account) => { @@ -379,15 +366,7 @@ pub fn withdraw_withheld_tokens_from_mint( if proof_instruction_offset != 1 { return Err(TokenError::InvalidProofInstructionOffset.into()); } - match proof_data { - ProofData::InstructionData(data) => { - instructions.push(verify_ciphertext_ciphertext_equality(None, data)) - } - ProofData::RecordAccount(address, offset) => instructions.push( - ProofInstruction::VerifyCiphertextCiphertextEquality - .encode_verify_proof_from_account(None, address, offset), - ), - }; + instructions.push(verify_ciphertext_ciphertext_equality(None, proof_data)); }; Ok(instructions) @@ -416,11 +395,8 @@ pub fn inner_withdraw_withheld_tokens_from_accounts( ]; let proof_instruction_offset = match proof_data_location { - ProofLocation::InstructionOffset(proof_instruction_offset, proof_data) => { + ProofLocation::InstructionOffset(proof_instruction_offset, _) => { accounts.push(AccountMeta::new_readonly(sysvar::instructions::id(), false)); - if let ProofData::RecordAccount(record_address, _) = proof_data { - accounts.push(AccountMeta::new_readonly(*record_address, false)); - } proof_instruction_offset.into() } ProofLocation::ContextStateAccount(context_state_account) => { @@ -490,15 +466,7 @@ pub fn withdraw_withheld_tokens_from_accounts( if proof_instruction_offset != 1 { return Err(TokenError::InvalidProofInstructionOffset.into()); } - match proof_data { - ProofData::InstructionData(data) => { - instructions.push(verify_ciphertext_ciphertext_equality(None, data)) - } - ProofData::RecordAccount(address, offset) => instructions.push( - ProofInstruction::VerifyCiphertextCiphertextEquality - .encode_verify_proof_from_account(None, address, offset), - ), - }; + instructions.push(verify_ciphertext_ciphertext_equality(None, proof_data)); }; Ok(instructions) diff --git a/token/program-2022/src/extension/confidential_transfer_fee/processor.rs b/token/program-2022/src/extension/confidential_transfer_fee/processor.rs index 26ee3a9c235..4fa079ec0b4 100644 --- a/token/program-2022/src/extension/confidential_transfer_fee/processor.rs +++ b/token/program-2022/src/extension/confidential_transfer_fee/processor.rs @@ -42,7 +42,6 @@ use { sysvar::instructions::get_instruction_relative, }, spl_pod::{bytemuck::pod_from_bytes, optional_keys::OptionalNonZeroPubkey}, - std::slice::Iter, }; /// Processes an [InitializeConfidentialTransferFeeConfig] instruction. @@ -80,8 +79,10 @@ fn process_withdraw_withheld_tokens_from_mint( // zero-knowledge proof certifies that the exact withheld amount is credited to // the destination account. - let proof_context = - verify_ciphertext_ciphertext_equality_proof(account_info_iter, proof_instruction_offset)?; + let proof_context = verify_ciphertext_ciphertext_equality_proof( + next_account_info(account_info_iter)?, + proof_instruction_offset, + )?; let authority_info = next_account_info(account_info_iter)?; let authority_info_data_len = authority_info.data_len(); @@ -174,14 +175,13 @@ fn process_withdraw_withheld_tokens_from_mint( /// instruction or a `[WithdrawWithheldTokensFromAccounts]` and return the /// corresponding proof context. fn verify_ciphertext_ciphertext_equality_proof( - account_info_iter: &mut Iter<'_, AccountInfo<'_>>, + account_info: &AccountInfo<'_>, proof_instruction_offset: i64, ) -> Result<CiphertextCiphertextEqualityProofContext, ProgramError> { if proof_instruction_offset == 0 { - let context_account_info = next_account_info(account_info_iter)?; // interpret `account_info` as a context state account - check_zk_token_proof_program_account(context_account_info.owner)?; - let context_state_account_data = context_account_info.data.borrow(); + check_zk_token_proof_program_account(account_info.owner)?; + let context_state_account_data = account_info.data.borrow(); let context_state = pod_from_bytes::< ProofContextState<CiphertextCiphertextEqualityProofContext>, >(&context_state_account_data)?; @@ -192,15 +192,12 @@ fn verify_ciphertext_ciphertext_equality_proof( Ok(context_state.proof_context) } else { - let sysvar_account_info = next_account_info(account_info_iter)?; // interpret `account_info` as a sysvar - let zkp_instruction = - get_instruction_relative(proof_instruction_offset, sysvar_account_info)?; - Ok(decode_proof_instruction_context::< + let zkp_instruction = get_instruction_relative(proof_instruction_offset, account_info)?; + Ok(*decode_proof_instruction_context::< CiphertextCiphertextEqualityProofData, CiphertextCiphertextEqualityProofContext, >( - account_info_iter, ProofInstruction::VerifyCiphertextCiphertextEquality, &zkp_instruction, )?) @@ -222,8 +219,10 @@ fn process_withdraw_withheld_tokens_from_accounts( // zero-knowledge proof certifies that the exact aggregate withheld amount is // credited to the destination account. - let proof_context = - verify_ciphertext_ciphertext_equality_proof(account_info_iter, proof_instruction_offset)?; + let proof_context = verify_ciphertext_ciphertext_equality_proof( + next_account_info(account_info_iter)?, + proof_instruction_offset, + )?; let authority_info = next_account_info(account_info_iter)?; let authority_info_data_len = authority_info.data_len(); diff --git a/token/program-2022/src/proof.rs b/token/program-2022/src/proof.rs index d0dcf9efc2d..fbb9b525a10 100644 --- a/token/program-2022/src/proof.rs +++ b/token/program-2022/src/proof.rs @@ -2,31 +2,20 @@ use { bytemuck::Pod, - solana_program::{ - account_info::{next_account_info, AccountInfo}, - instruction::Instruction, - msg, - program_error::ProgramError, - pubkey::Pubkey, - }, + solana_program::{instruction::Instruction, msg, program_error::ProgramError, pubkey::Pubkey}, solana_zk_token_sdk::{ instruction::ZkProofData, zk_token_proof_instruction::ProofInstruction, zk_token_proof_program, }, - std::{num::NonZeroI8, slice::Iter}, + std::num::NonZeroI8, }; -/// If a proof is to be read from a record account, the proof instruction data -/// must be 5 bytes: 1 byte for the proof type and 4 bytes for the u32 offset -const INSTRUCTION_DATA_LENGTH_WITH_RECORD_ACCOUNT: usize = 5; - /// Decodes the proof context data associated with a zero-knowledge proof /// instruction. pub fn decode_proof_instruction_context<T: Pod + ZkProofData<U>, U: Pod>( - account_info_iter: &mut Iter<'_, AccountInfo<'_>>, expected: ProofInstruction, instruction: &Instruction, -) -> Result<U, ProgramError> { +) -> Result<&U, ProgramError> { if instruction.program_id != zk_token_proof_program::id() || ProofInstruction::instruction_type(&instruction.data) != Some(expected) { @@ -34,31 +23,9 @@ pub fn decode_proof_instruction_context<T: Pod + ZkProofData<U>, U: Pod>( return Err(ProgramError::InvalidInstructionData); } - // If the instruction data size is exactly 5 bytes, then interpret it as an - // offset byte for a record account. This behavior is identical to that of - // the ZK ElGamal proof program. - if instruction.data.len() == INSTRUCTION_DATA_LENGTH_WITH_RECORD_ACCOUNT { - let record_account = next_account_info(account_info_iter)?; - - // first byte is the proof type - let start_offset = u32::from_le_bytes(instruction.data[1..].try_into().unwrap()) as usize; - let end_offset = start_offset - .checked_add(std::mem::size_of::<T>()) - .ok_or(ProgramError::InvalidAccountData)?; - - let record_account_data = record_account.data.borrow(); - let raw_proof_data = record_account_data - .get(start_offset..end_offset) - .ok_or(ProgramError::AccountDataTooSmall)?; - - bytemuck::try_from_bytes::<T>(raw_proof_data) - .map(|proof_data| *ZkProofData::context_data(proof_data)) - .map_err(|_| ProgramError::InvalidAccountData) - } else { - ProofInstruction::proof_data::<T, U>(&instruction.data) - .map(|proof_data| *ZkProofData::context_data(proof_data)) - .ok_or(ProgramError::InvalidInstructionData) - } + ProofInstruction::proof_data::<T, U>(&instruction.data) + .map(ZkProofData::context_data) + .ok_or(ProgramError::InvalidInstructionData) } /// A proof location type meant to be used for arguments to instruction @@ -67,22 +34,11 @@ pub fn decode_proof_instruction_context<T: Pod + ZkProofData<U>, U: Pod>( pub enum ProofLocation<'a, T> { /// The proof is included in the same transaction of a corresponding /// token-2022 instruction. - InstructionOffset(NonZeroI8, ProofData<'a, T>), + InstructionOffset(NonZeroI8, &'a T), /// The proof is pre-verified into a context state account. ContextStateAccount(&'a Pubkey), } -/// A proof data type to distinguish between proof data included as part of -/// zk-token proof instruction data and proof data stored in a record account. -#[derive(Clone, Copy)] -pub enum ProofData<'a, T> { - /// The proof data - InstructionData(&'a T), - /// The address of a record account containing the proof data and its byte - /// offset - RecordAccount(&'a Pubkey, u32), -} - /// Instruction options for when using split context state accounts #[derive(Clone, Copy)] pub struct SplitContextStateAccountsConfig {