diff --git a/programs/zk-token-proof-tests/tests/process_transaction.rs b/programs/zk-token-proof-tests/tests/process_transaction.rs index 555295e4e9a6ed..2564c9805517d5 100644 --- a/programs/zk-token-proof-tests/tests/process_transaction.rs +++ b/programs/zk-token-proof-tests/tests/process_transaction.rs @@ -9,19 +9,24 @@ use { transaction::{Transaction, TransactionError}, }, solana_zk_token_sdk::{ - encryption::elgamal::ElGamalKeypair, instruction::*, zk_token_proof_instruction::*, - zk_token_proof_program, zk_token_proof_state::ProofContextState, + encryption::{elgamal::ElGamalKeypair, pedersen::*}, + instruction::*, + zk_token_proof_instruction::*, + zk_token_proof_program, + zk_token_proof_state::ProofContextState, }, std::mem::size_of, }; -const VERIFY_INSTRUCTION_TYPES: [ProofInstruction; 6] = [ +const VERIFY_INSTRUCTION_TYPES: [ProofInstruction; 8] = [ ProofInstruction::VerifyCloseAccount, ProofInstruction::VerifyWithdraw, ProofInstruction::VerifyWithdrawWithheldTokens, ProofInstruction::VerifyTransfer, ProofInstruction::VerifyTransferWithFee, ProofInstruction::VerifyPubkeyValidity, + ProofInstruction::VerifyValidityProof, + ProofInstruction::VerifyAggregatedValidityProof, ]; #[tokio::test] @@ -318,6 +323,137 @@ async fn test_pubkey_validity() { .await; } +#[tokio::test] +async fn test_validity_proof() { + let destination_pubkey = ElGamalKeypair::new_rand().public; + let auditor_pubkey = ElGamalKeypair::new_rand().public; + + let amount: u64 = 55; + let (commitment, opening) = Pedersen::new(amount); + + let destination_handle = destination_pubkey.decrypt_handle(&opening); + let auditor_handle = auditor_pubkey.decrypt_handle(&opening); + + let success_proof_data = ValidityProofData::new( + &destination_pubkey, + &auditor_pubkey, + &commitment, + &destination_handle, + &auditor_handle, + amount, + &opening, + ) + .unwrap(); + + let incorrect_amount: u64 = 0; + let fail_proof_data = ValidityProofData::new( + &destination_pubkey, + &auditor_pubkey, + &commitment, + &destination_handle, + &auditor_handle, + incorrect_amount, + &opening, + ) + .unwrap(); + + test_verify_proof_without_context( + ProofInstruction::VerifyValidityProof, + &success_proof_data, + &fail_proof_data, + ) + .await; + + test_verify_proof_with_context( + ProofInstruction::VerifyValidityProof, + size_of::>(), + &success_proof_data, + &fail_proof_data, + ) + .await; + + test_close_context_state( + ProofInstruction::VerifyValidityProof, + size_of::>(), + &success_proof_data, + ) + .await; +} + +#[tokio::test] +async fn test_aggregated_validity_proof() { + let destination_pubkey = ElGamalKeypair::new_rand().public; + let auditor_pubkey = ElGamalKeypair::new_rand().public; + + let amount_lo: u64 = 55; + let amount_hi: u64 = 77; + + let (commitment_lo, opening_lo) = Pedersen::new(amount_lo); + let (commitment_hi, opening_hi) = Pedersen::new(amount_hi); + + let destination_handle_lo = destination_pubkey.decrypt_handle(&opening_lo); + let destination_handle_hi = destination_pubkey.decrypt_handle(&opening_hi); + + let auditor_handle_lo = auditor_pubkey.decrypt_handle(&opening_lo); + let auditor_handle_hi = auditor_pubkey.decrypt_handle(&opening_hi); + + let success_proof_data = AggregatedValidityProofData::new( + &destination_pubkey, + &auditor_pubkey, + &commitment_lo, + &commitment_hi, + &destination_handle_lo, + &destination_handle_hi, + &auditor_handle_lo, + &auditor_handle_hi, + amount_lo, + amount_hi, + &opening_lo, + &opening_hi, + ) + .unwrap(); + + let incorrect_amount_lo: u64 = 0; + let incorrect_amount_hi: u64 = 0; + let fail_proof_data = AggregatedValidityProofData::new( + &destination_pubkey, + &auditor_pubkey, + &commitment_lo, + &commitment_hi, + &destination_handle_lo, + &destination_handle_hi, + &auditor_handle_lo, + &auditor_handle_hi, + incorrect_amount_lo, + incorrect_amount_hi, + &opening_lo, + &opening_hi, + ) + .unwrap(); + + test_verify_proof_without_context( + ProofInstruction::VerifyAggregatedValidityProof, + &success_proof_data, + &fail_proof_data, + ) + .await; + + test_verify_proof_with_context( + ProofInstruction::VerifyAggregatedValidityProof, + size_of::>(), + &success_proof_data, + &fail_proof_data, + ) + .await; + + test_close_context_state( + ProofInstruction::VerifyAggregatedValidityProof, + size_of::>(), + &success_proof_data, + ) + .await; +} + async fn test_verify_proof_without_context( proof_instruction: ProofInstruction, success_proof_data: &T, diff --git a/programs/zk-token-proof/src/lib.rs b/programs/zk-token-proof/src/lib.rs index 786113a0d23efe..63ae42d88d8161 100644 --- a/programs/zk-token-proof/src/lib.rs +++ b/programs/zk-token-proof/src/lib.rs @@ -191,5 +191,21 @@ declare_process_instruction!(process_instruction, 0, |invoke_context| { ic_msg!(invoke_context, "VerifyPubkeyValidity"); process_verify_proof::(invoke_context) } + ProofInstruction::VerifyValidityProof => { + ic_msg!(invoke_context, "VerifyValidityProof"); + process_verify_proof::(invoke_context) + } + ProofInstruction::VerifyAggregatedValidityProof => { + ic_msg!(invoke_context, "VerifyAggregatedValidityProof"); + process_verify_proof::( + invoke_context, + ) + } + ProofInstruction::VerifyCtxtCommEqualityProof => { + ic_msg!(invoke_context, "VerifyCtxtCommEqualityProof"); + process_verify_proof::( + invoke_context, + ) + } } }); diff --git a/zk-token-sdk/src/instruction/equality_proof.rs b/zk-token-sdk/src/instruction/equality_proof.rs new file mode 100644 index 00000000000000..9f3f620da00275 --- /dev/null +++ b/zk-token-sdk/src/instruction/equality_proof.rs @@ -0,0 +1,127 @@ +#[cfg(not(target_os = "solana"))] +use { + crate::{ + encryption::{ + elgamal::{ElGamalCiphertext, ElGamalKeypair}, + pedersen::{PedersenCommitment, PedersenOpening}, + }, + errors::ProofError, + sigma_proofs::equality_proof::CtxtCommEqualityProof, + transcript::TranscriptProtocol, + }, + merlin::Transcript, +}; +use { + crate::{ + instruction::{ProofType, ZkProofData}, + zk_token_elgamal::pod, + }, + bytemuck::{Pod, Zeroable}, +}; + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct CtxtCommEqualityProofData { + /// The context data for the ciphertext-commitment equality proof instruction + pub context: CtxtCommEqualityProofContext, // 128 bytes + + /// Proof that an ElGamal ciphertext is valid + pub proof: pod::CtxtCommEqualityProof, // 192 bytes +} + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct CtxtCommEqualityProofContext { + /// The ElGamal pubkey + pub pubkey: pod::ElGamalPubkey, // 32 bytes + + /// The ciphertext encrypted under the ElGamal pubkey + pub ciphertext: pod::ElGamalCiphertext, // 64 bytes + + /// The Pedersen commitment + pub commitment: pod::PedersenCommitment, // 32 bytes +} + +#[cfg(not(target_os = "solana"))] +impl CtxtCommEqualityProofData { + pub fn new( + keypair: &ElGamalKeypair, + ciphertext: &ElGamalCiphertext, + commitment: &PedersenCommitment, + amount: u64, + opening: &PedersenOpening, + ) -> Result { + let context = CtxtCommEqualityProofContext { + pubkey: pod::ElGamalPubkey(keypair.public.to_bytes()), + ciphertext: pod::ElGamalCiphertext(ciphertext.to_bytes()), + commitment: pod::PedersenCommitment(commitment.to_bytes()), + }; + + let mut transcript = CtxtCommEqualityProofData::transcript_new(&context); + + let proof = + CtxtCommEqualityProof::new(keypair, ciphertext, amount, opening, &mut transcript); + + Ok(CtxtCommEqualityProofData { + context, + proof: proof.into(), + }) + } +} + +impl ZkProofData for CtxtCommEqualityProofData { + const PROOF_TYPE: ProofType = ProofType::CtxtCommEqualityProof; + + fn context_data(&self) -> &CtxtCommEqualityProofContext { + &self.context + } + + #[cfg(not(target_os = "solana"))] + fn verify_proof(&self) -> Result<(), ProofError> { + let mut transcript = CtxtCommEqualityProofData::transcript_new(&self.context); + + let pubkey = self.context.pubkey.try_into()?; + let ciphertext = self.context.ciphertext.try_into()?; + let commitment = self.context.commitment.try_into()?; + + let proof: CtxtCommEqualityProof = self.proof.try_into()?; + proof + .verify(&pubkey, &ciphertext, &commitment, &mut transcript) + .map_err(|e| e.into()) + } +} + +impl CtxtCommEqualityProofData { + fn transcript_new(context: &CtxtCommEqualityProofContext) -> Transcript { + let mut transcript = Transcript::new(b"CtxtCommEqualityProof"); + + transcript.append_pubkey(b"pubkey", &context.pubkey); + transcript.append_ciphertext(b"ciphertext", &context.ciphertext); + transcript.append_commitment(b"commitment", &context.commitment); + + transcript + } +} + +#[cfg(test)] +mod test { + use { + super::*, + crate::encryption::{elgamal::ElGamalKeypair, pedersen::Pedersen}, + }; + + #[test] + fn test_ctxt_comm_equality_proof_correctness() { + let keypair = ElGamalKeypair::new_rand(); + let amount: u64 = 55; + + let ciphertext = keypair.public.encrypt(amount); + let (commitment, opening) = Pedersen::new(amount); + + let ctxt_comm_equality_proof_data = + CtxtCommEqualityProofData::new(&keypair, &ciphertext, &commitment, amount, &opening) + .unwrap(); + + assert!(ctxt_comm_equality_proof_data.verify_proof().is_ok()); + } +} diff --git a/zk-token-sdk/src/instruction/mod.rs b/zk-token-sdk/src/instruction/mod.rs index f257ee961a1a4e..6bd231db23ac46 100644 --- a/zk-token-sdk/src/instruction/mod.rs +++ b/zk-token-sdk/src/instruction/mod.rs @@ -1,7 +1,9 @@ pub mod close_account; +pub mod equality_proof; pub mod pubkey_validity; pub mod transfer; pub mod transfer_with_fee; +pub mod validity_proof; pub mod withdraw; pub mod withdraw_withheld; @@ -20,9 +22,14 @@ use { pub use { bytemuck::Pod, close_account::{CloseAccountData, CloseAccountProofContext}, + equality_proof::{CtxtCommEqualityProofContext, CtxtCommEqualityProofData}, pubkey_validity::{PubkeyValidityData, PubkeyValidityProofContext}, transfer::{TransferData, TransferProofContext}, transfer_with_fee::{FeeParameters, TransferWithFeeData, TransferWithFeeProofContext}, + validity_proof::{ + AggregatedValidityProofContext, AggregatedValidityProofData, ValidityProofContext, + ValidityProofData, + }, withdraw::{WithdrawData, WithdrawProofContext}, withdraw_withheld::{WithdrawWithheldTokensData, WithdrawWithheldTokensProofContext}, }; @@ -38,6 +45,9 @@ pub enum ProofType { Transfer, TransferWithFee, PubkeyValidity, + ValidityProof, + AggregatedValidityProof, + CtxtCommEqualityProof, } pub trait ZkProofData { diff --git a/zk-token-sdk/src/instruction/validity_proof.rs b/zk-token-sdk/src/instruction/validity_proof.rs new file mode 100644 index 00000000000000..de32ac98c28d17 --- /dev/null +++ b/zk-token-sdk/src/instruction/validity_proof.rs @@ -0,0 +1,326 @@ +#[cfg(not(target_os = "solana"))] +use { + crate::{ + encryption::{ + elgamal::{DecryptHandle, ElGamalPubkey}, + pedersen::{PedersenCommitment, PedersenOpening}, + }, + errors::ProofError, + sigma_proofs::validity_proof::{AggregatedValidityProof, ValidityProof}, + transcript::TranscriptProtocol, + }, + merlin::Transcript, +}; +use { + crate::{ + instruction::{ProofType, ZkProofData}, + zk_token_elgamal::pod, + }, + bytemuck::{Pod, Zeroable}, +}; + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct ValidityProofData { + /// The context data for the (ciphertext) validity proof instruction + pub context: ValidityProofContext, // 160 bytes + + /// Proof that an ElGamal ciphertext is valid + pub proof: pod::ValidityProof, // 160 bytes +} + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct ValidityProofContext { + /// The destination pubkey + pub destination_pubkey: pod::ElGamalPubkey, // 32 bytes + + /// The auditor pubkey + pub auditor_pubkey: pod::ElGamalPubkey, // 32 bytes + + /// The commitment that the proof validates + pub commitment: pod::PedersenCommitment, // 32 bytes + + /// The destination decryption handle + pub destination_handle: pod::DecryptHandle, // 32 bytes + + /// The auditor decryption handles + pub auditor_handle: pod::DecryptHandle, // 32 bytes +} + +#[cfg(not(target_os = "solana"))] +impl ValidityProofData { + pub fn new( + destination_pubkey: &ElGamalPubkey, + auditor_pubkey: &ElGamalPubkey, + commitment: &PedersenCommitment, + destination_handle: &DecryptHandle, + auditor_handle: &DecryptHandle, + amount: u64, + opening: &PedersenOpening, + ) -> Result { + let context = ValidityProofContext { + destination_pubkey: pod::ElGamalPubkey(destination_pubkey.to_bytes()), + auditor_pubkey: pod::ElGamalPubkey(auditor_pubkey.to_bytes()), + commitment: pod::PedersenCommitment(commitment.to_bytes()), + destination_handle: pod::DecryptHandle(destination_handle.to_bytes()), + auditor_handle: pod::DecryptHandle(auditor_handle.to_bytes()), + }; + + let mut transcript = ValidityProof::transcript_new(&context); + + let proof = ValidityProof::new( + (destination_pubkey, auditor_pubkey), + amount, + opening, + &mut transcript, + ); + + Ok(ValidityProofData { + context, + proof: proof.into(), + }) + } +} + +impl ZkProofData for ValidityProofData { + const PROOF_TYPE: ProofType = ProofType::ValidityProof; + + fn context_data(&self) -> &ValidityProofContext { + &self.context + } + + #[cfg(not(target_os = "solana"))] + fn verify_proof(&self) -> Result<(), ProofError> { + let mut transcript = ValidityProof::transcript_new(&self.context); + + let destination_pubkey = self.context.destination_pubkey.try_into()?; + let auditor_pubkey = self.context.auditor_pubkey.try_into()?; + let commitment = self.context.commitment.try_into()?; + let destination_handle = self.context.destination_handle.try_into()?; + let auditor_handle = self.context.auditor_handle.try_into()?; + + let proof: ValidityProof = self.proof.try_into()?; + proof + .verify( + &commitment, + (&destination_pubkey, &auditor_pubkey), + (&destination_handle, &auditor_handle), + &mut transcript, + ) + .map_err(|e| e.into()) + } +} + +impl ValidityProof { + fn transcript_new(context: &ValidityProofContext) -> Transcript { + let mut transcript = Transcript::new(b"ValidityProof"); + + transcript.append_pubkey(b"pubkey", &context.destination_pubkey); + transcript.append_pubkey(b"pubkey", &context.auditor_pubkey); + transcript.append_commitment(b"commitment", &context.commitment); + transcript.append_handle(b"decrypt_handle", &context.destination_handle); + transcript.append_handle(b"decrypt_handle", &context.auditor_handle); + + transcript + } +} + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct AggregatedValidityProofData { + /// The context data for the aggregate validity proof instruction + pub context: AggregatedValidityProofContext, // 32 bytes + + /// Proof that a pair of ciphertexts are valid + pub proof: pod::AggregatedValidityProof, // 256 bytes +} + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct AggregatedValidityProofContext { + /// The destination pubkey + pub destination_pubkey: pod::ElGamalPubkey, // 32 bytes + + /// The auditor pubkey + pub auditor_pubkey: pod::ElGamalPubkey, // 32 bytes + + /// The first commitment that the proof validates + pub commitment_lo: pod::PedersenCommitment, // 32 bytes + + /// The second commitment that the proof validates + pub commitment_hi: pod::PedersenCommitment, // 32 bytes + + /// The destination decryption handle for the first commitment + pub destination_handle_lo: pod::DecryptHandle, // 32 bytes + + /// The destination decryption handle for the second commitment + pub destination_handle_hi: pod::DecryptHandle, // 32 bytes + + /// The auditor decryption handle for the first commitment + pub auditor_handle_lo: pod::DecryptHandle, // 32 bytes + + /// The auditor decryption handle for the second commitment + pub auditor_handle_hi: pod::DecryptHandle, // 32 bytes +} + +#[cfg(not(target_os = "solana"))] +#[allow(clippy::too_many_arguments)] +impl AggregatedValidityProofData { + pub fn new( + destination_pubkey: &ElGamalPubkey, + auditor_pubkey: &ElGamalPubkey, + commitment_lo: &PedersenCommitment, + commitment_hi: &PedersenCommitment, + destination_handle_lo: &DecryptHandle, + destination_handle_hi: &DecryptHandle, + auditor_handle_lo: &DecryptHandle, + auditor_handle_hi: &DecryptHandle, + amount_lo: u64, + amount_hi: u64, + opening_lo: &PedersenOpening, + opening_hi: &PedersenOpening, + ) -> Result { + let context = AggregatedValidityProofContext { + destination_pubkey: pod::ElGamalPubkey(destination_pubkey.to_bytes()), + auditor_pubkey: pod::ElGamalPubkey(auditor_pubkey.to_bytes()), + commitment_lo: pod::PedersenCommitment(commitment_lo.to_bytes()), + commitment_hi: pod::PedersenCommitment(commitment_hi.to_bytes()), + destination_handle_lo: pod::DecryptHandle(destination_handle_lo.to_bytes()), + destination_handle_hi: pod::DecryptHandle(destination_handle_hi.to_bytes()), + auditor_handle_lo: pod::DecryptHandle(auditor_handle_lo.to_bytes()), + auditor_handle_hi: pod::DecryptHandle(auditor_handle_hi.to_bytes()), + }; + + let mut transcript = AggregatedValidityProof::transcript_new(&context); + + let proof = AggregatedValidityProof::new( + (destination_pubkey, auditor_pubkey), + (amount_lo, amount_hi), + (opening_lo, opening_hi), + &mut transcript, + ); + + Ok(AggregatedValidityProofData { + context, + proof: proof.into(), + }) + } +} + +impl ZkProofData for AggregatedValidityProofData { + const PROOF_TYPE: ProofType = ProofType::AggregatedValidityProof; + + fn context_data(&self) -> &AggregatedValidityProofContext { + &self.context + } + + #[cfg(not(target_os = "solana"))] + fn verify_proof(&self) -> Result<(), ProofError> { + let mut transcript = AggregatedValidityProof::transcript_new(&self.context); + + let destination_pubkey = self.context.destination_pubkey.try_into()?; + let auditor_pubkey = self.context.auditor_pubkey.try_into()?; + let commitment_lo = self.context.commitment_lo.try_into()?; + let commitment_hi = self.context.commitment_hi.try_into()?; + let destination_handle_lo = self.context.destination_handle_lo.try_into()?; + let destination_handle_hi = self.context.destination_handle_hi.try_into()?; + let auditor_handle_lo = self.context.auditor_handle_lo.try_into()?; + let auditor_handle_hi = self.context.auditor_handle_hi.try_into()?; + + let proof: AggregatedValidityProof = self.proof.try_into()?; + proof + .verify( + (&destination_pubkey, &auditor_pubkey), + (&commitment_lo, &commitment_hi), + (&destination_handle_lo, &destination_handle_hi), + (&auditor_handle_lo, &auditor_handle_hi), + &mut transcript, + ) + .map_err(|e| e.into()) + } +} + +impl AggregatedValidityProof { + fn transcript_new(context: &AggregatedValidityProofContext) -> Transcript { + let mut transcript = Transcript::new(b"AggregatedValidityProof"); + + transcript.append_pubkey(b"pubkey", &context.destination_pubkey); + transcript.append_pubkey(b"pubkey", &context.auditor_pubkey); + transcript.append_commitment(b"commitment", &context.commitment_lo); + transcript.append_commitment(b"commitment", &context.commitment_hi); + transcript.append_handle(b"decrypt_handle", &context.destination_handle_lo); + transcript.append_handle(b"decrypt_handle", &context.destination_handle_hi); + transcript.append_handle(b"decrypt_handle", &context.auditor_handle_lo); + transcript.append_handle(b"decrypt_handle", &context.auditor_handle_hi); + + transcript + } +} + +#[cfg(test)] +mod test { + use { + super::*, + crate::encryption::{elgamal::ElGamalKeypair, pedersen::Pedersen}, + }; + + #[test] + fn test_validity_proof_correctness() { + let destination_pubkey = ElGamalKeypair::new_rand().public; + let auditor_pubkey = ElGamalKeypair::new_rand().public; + + let amount: u64 = 55; + let (commitment, opening) = Pedersen::new(amount); + + let destination_handle = destination_pubkey.decrypt_handle(&opening); + let auditor_handle = auditor_pubkey.decrypt_handle(&opening); + + let validity_proof_data = ValidityProofData::new( + &destination_pubkey, + &auditor_pubkey, + &commitment, + &destination_handle, + &auditor_handle, + amount, + &opening, + ) + .unwrap(); + assert!(validity_proof_data.verify_proof().is_ok()); + } + + #[test] + fn test_aggregated_validity_proof_correctness() { + let destination_pubkey = ElGamalKeypair::new_rand().public; + let auditor_pubkey = ElGamalKeypair::new_rand().public; + + let amount_lo: u64 = 55; + let amount_hi: u64 = 77; + + let (commitment_lo, opening_lo) = Pedersen::new(amount_lo); + let (commitment_hi, opening_hi) = Pedersen::new(amount_hi); + + let destination_handle_lo = destination_pubkey.decrypt_handle(&opening_lo); + let destination_handle_hi = destination_pubkey.decrypt_handle(&opening_hi); + + let auditor_handle_lo = auditor_pubkey.decrypt_handle(&opening_lo); + let auditor_handle_hi = auditor_pubkey.decrypt_handle(&opening_hi); + + let aggregated_validity_proof_data = AggregatedValidityProofData::new( + &destination_pubkey, + &auditor_pubkey, + &commitment_lo, + &commitment_hi, + &destination_handle_lo, + &destination_handle_hi, + &auditor_handle_lo, + &auditor_handle_hi, + amount_lo, + amount_hi, + &opening_lo, + &opening_hi, + ) + .unwrap(); + assert!(aggregated_validity_proof_data.verify_proof().is_ok()); + } +} diff --git a/zk-token-sdk/src/zk_token_proof_instruction.rs b/zk-token-sdk/src/zk_token_proof_instruction.rs index 21d1dae975562d..bd0d796363fafb 100644 --- a/zk-token-sdk/src/zk_token_proof_instruction.rs +++ b/zk-token-sdk/src/zk_token_proof_instruction.rs @@ -132,6 +132,60 @@ pub enum ProofInstruction { /// `PubkeyValidityData` /// VerifyPubkeyValidity, + + /// Verify a (ciphertext) validity proof. + /// + /// This instruction can be configured to optionally create a proof context state account. + /// + /// Accounts expected by this instruction: + /// + /// * Creating a proof context account + /// 0. `[writable]` The proof context account + /// 1. `[]` The proof context account owner + /// + /// * Otherwise + /// None + /// + /// Data expected by this instruction: + /// `ValidityProofData` + /// + VerifyValidityProof, + + /// Verify a (ciphertext) aggregated validity proof. + /// + /// This instruction can be configured to optionally create a proof context state account. + /// + /// Accounts expected by this instruction: + /// + /// * Creating a proof context account + /// 0. `[writable]` The proof context account + /// 1. `[]` The proof context account owner + /// + /// * Otherwise + /// None + /// + /// Data expected by this instruction: + /// `AggregatedValidityProofData` + /// + VerifyAggregatedValidityProof, + + /// Verify a ciphertext-commitment equality proof. + /// + /// This instruction can be configured to optionally create a proof context state account. + /// + /// Accounts expected by this instruction: + /// + /// * Creating a proof context account + /// 0. `[writable]` The proof context account + /// 1. `[]` The proof context account owner + /// + /// * Otherwise + /// None + /// + /// Data expected by this instruction: + /// `AggregatedValidityProofData` + /// + VerifyCtxtCommEqualityProof, } /// Pubkeys associated with a context state account to be used as parameters to functions.