From 4796e2fd84e4a05ac0affb98e2397ebd85903328 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Sat, 20 May 2023 07:08:40 +0900 Subject: [PATCH] [zk-token-sdk] Generate proof transcript directly from proof contexts (#31725) * generate transcript directly from proof contexts * Update zk-token-sdk/src/instruction/transfer.rs Co-authored-by: Jon Cinque * Update zk-token-sdk/src/instruction/transfer.rs Co-authored-by: Jon Cinque --------- Co-authored-by: Jon Cinque --- .../src/instruction/ctxt_ctxt_equality.rs | 31 ++---- .../src/instruction/pubkey_validity.rs | 10 +- zk-token-sdk/src/instruction/transfer.rs | 59 ++++-------- .../src/instruction/transfer_with_fee.rs | 94 +++++-------------- zk-token-sdk/src/instruction/withdraw.rs | 30 +++--- zk-token-sdk/src/instruction/zero_balance.rs | 17 ++-- 6 files changed, 79 insertions(+), 162 deletions(-) diff --git a/zk-token-sdk/src/instruction/ctxt_ctxt_equality.rs b/zk-token-sdk/src/instruction/ctxt_ctxt_equality.rs index 0451c05c68..de2e8e07de 100644 --- a/zk-token-sdk/src/instruction/ctxt_ctxt_equality.rs +++ b/zk-token-sdk/src/instruction/ctxt_ctxt_equality.rs @@ -78,12 +78,7 @@ impl CiphertextCiphertextEqualityProofData { destination_ciphertext: pod_destination_ciphertext, }; - let mut transcript = CiphertextCiphertextEqualityProof::transcript_new( - &pod_source_pubkey, - &pod_destination_pubkey, - &pod_source_ciphertext, - &pod_destination_ciphertext, - ); + let mut transcript = context.new_transcript(); let proof = CiphertextCiphertextEqualityProof::new( source_keypair, @@ -110,12 +105,7 @@ impl ZkProofData #[cfg(not(target_os = "solana"))] fn verify_proof(&self) -> Result<(), ProofError> { - let mut transcript = CiphertextCiphertextEqualityProof::transcript_new( - &self.context.source_pubkey, - &self.context.destination_pubkey, - &self.context.source_ciphertext, - &self.context.destination_ciphertext, - ); + let mut transcript = self.context.new_transcript(); let source_pubkey = self.context.source_pubkey.try_into()?; let destination_pubkey = self.context.destination_pubkey.try_into()?; @@ -137,20 +127,15 @@ impl ZkProofData #[allow(non_snake_case)] #[cfg(not(target_os = "solana"))] -impl CiphertextCiphertextEqualityProof { - fn transcript_new( - source_pubkey: &pod::ElGamalPubkey, - destination_pubkey: &pod::ElGamalPubkey, - source_ciphertext: &pod::ElGamalCiphertext, - destination_ciphertext: &pod::ElGamalCiphertext, - ) -> Transcript { +impl CiphertextCiphertextEqualityProofContext { + fn new_transcript(&self) -> Transcript { let mut transcript = Transcript::new(b"CiphertextCiphertextEqualityProof"); - transcript.append_pubkey(b"pubkey-source", source_pubkey); - transcript.append_pubkey(b"pubkey-dest", destination_pubkey); + transcript.append_pubkey(b"source-pubkey", &self.source_pubkey); + transcript.append_pubkey(b"destination-pubkey", &self.destination_pubkey); - transcript.append_ciphertext(b"ciphertext-source", source_ciphertext); - transcript.append_ciphertext(b"ciphertext-dest", destination_ciphertext); + transcript.append_ciphertext(b"source-ciphertext", &self.source_ciphertext); + transcript.append_ciphertext(b"destination-ciphertext", &self.destination_ciphertext); transcript } diff --git a/zk-token-sdk/src/instruction/pubkey_validity.rs b/zk-token-sdk/src/instruction/pubkey_validity.rs index adaca3e7cc..699b18885b 100644 --- a/zk-token-sdk/src/instruction/pubkey_validity.rs +++ b/zk-token-sdk/src/instruction/pubkey_validity.rs @@ -52,7 +52,7 @@ impl PubkeyValidityData { let context = PubkeyValidityProofContext { pubkey: pod_pubkey }; - let mut transcript = PubkeyValidityProof::transcript_new(&pod_pubkey); + let mut transcript = context.new_transcript(); let proof = PubkeyValidityProof::new(keypair, &mut transcript).into(); Ok(PubkeyValidityData { context, proof }) @@ -68,7 +68,7 @@ impl ZkProofData for PubkeyValidityData { #[cfg(not(target_os = "solana"))] fn verify_proof(&self) -> Result<(), ProofError> { - let mut transcript = PubkeyValidityProof::transcript_new(&self.context.pubkey); + let mut transcript = self.context.new_transcript(); let pubkey = self.context.pubkey.try_into()?; let proof: PubkeyValidityProof = self.proof.try_into()?; proof.verify(&pubkey, &mut transcript).map_err(|e| e.into()) @@ -77,10 +77,10 @@ impl ZkProofData for PubkeyValidityData { #[allow(non_snake_case)] #[cfg(not(target_os = "solana"))] -impl PubkeyValidityProof { - fn transcript_new(pubkey: &pod::ElGamalPubkey) -> Transcript { +impl PubkeyValidityProofContext { + fn new_transcript(&self) -> Transcript { let mut transcript = Transcript::new(b"PubkeyProof"); - transcript.append_pubkey(b"pubkey", pubkey); + transcript.append_pubkey(b"pubkey", &self.pubkey); transcript } } diff --git a/zk-token-sdk/src/instruction/transfer.rs b/zk-token-sdk/src/instruction/transfer.rs index c402f0328d..a153b6b307 100644 --- a/zk-token-sdk/src/instruction/transfer.rs +++ b/zk-token-sdk/src/instruction/transfer.rs @@ -17,6 +17,7 @@ use { transcript::TranscriptProtocol, }, arrayref::{array_ref, array_refs}, + bytemuck::bytes_of, merlin::Transcript, std::convert::TryInto, }; @@ -139,13 +140,7 @@ impl TransferData { new_source_ciphertext: pod_new_source_ciphertext, }; - let mut transcript = TransferProof::transcript_new( - &pod_transfer_pubkeys, - &pod_ciphertext_lo, - &pod_ciphertext_hi, - &pod_new_source_ciphertext, - ); - + let mut transcript = context.new_transcript(); let proof = TransferProof::new( (amount_lo, amount_hi), source_keypair, @@ -228,12 +223,7 @@ impl ZkProofData for TransferData { #[cfg(not(target_os = "solana"))] fn verify_proof(&self) -> Result<(), ProofError> { // generate transcript and append all public inputs - let mut transcript = TransferProof::transcript_new( - &self.context.transfer_pubkeys, - &self.context.ciphertext_lo, - &self.context.ciphertext_hi, - &self.context.new_source_ciphertext, - ); + let mut transcript = self.context.new_transcript(); let ciphertext_lo = self.context.ciphertext_lo.try_into()?; let ciphertext_hi = self.context.ciphertext_hi.try_into()?; @@ -250,6 +240,22 @@ impl ZkProofData for TransferData { } } +#[allow(non_snake_case)] +#[cfg(not(target_os = "solana"))] +impl TransferProofContext { + fn new_transcript(&self) -> Transcript { + let mut transcript = Transcript::new(b"transfer-proof"); + transcript.append_message(b"ciphertext-lo", bytes_of(&self.ciphertext_lo)); + transcript.append_message(b"ciphertext-hi", bytes_of(&self.ciphertext_hi)); + transcript.append_message(b"transfer-pubkeys", bytes_of(&self.transfer_pubkeys)); + transcript.append_message( + b"new-source-ciphertext", + bytes_of(&self.new_source_ciphertext), + ); + transcript + } +} + #[allow(non_snake_case)] #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] @@ -270,33 +276,6 @@ pub struct TransferProof { #[allow(non_snake_case)] #[cfg(not(target_os = "solana"))] impl TransferProof { - fn transcript_new( - transfer_pubkeys: &pod::TransferPubkeys, - ciphertext_lo: &pod::TransferAmountEncryption, - ciphertext_hi: &pod::TransferAmountEncryption, - new_source_ciphertext: &pod::ElGamalCiphertext, - ) -> Transcript { - let mut transcript = Transcript::new(b"transfer-proof"); - - transcript.append_pubkey(b"pubkey-source", &transfer_pubkeys.source_pubkey); - transcript.append_pubkey(b"pubkey-dest", &transfer_pubkeys.destination_pubkey); - transcript.append_pubkey(b"pubkey-auditor", &transfer_pubkeys.auditor_pubkey); - - transcript.append_commitment(b"comm-lo-amount", &ciphertext_lo.commitment); - transcript.append_handle(b"handle-lo-source", &ciphertext_lo.source_handle); - transcript.append_handle(b"handle-lo-dest", &ciphertext_lo.destination_handle); - transcript.append_handle(b"handle-lo-auditor", &ciphertext_lo.auditor_handle); - - transcript.append_commitment(b"comm-hi-amount", &ciphertext_hi.commitment); - transcript.append_handle(b"handle-hi-source", &ciphertext_hi.source_handle); - transcript.append_handle(b"handle-hi-dest", &ciphertext_hi.destination_handle); - transcript.append_handle(b"handle-hi-auditor", &ciphertext_hi.auditor_handle); - - transcript.append_ciphertext(b"ciphertext-new-source", new_source_ciphertext); - - transcript - } - pub fn new( (transfer_amount_lo, transfer_amount_hi): (u64, u64), source_keypair: &ElGamalKeypair, diff --git a/zk-token-sdk/src/instruction/transfer_with_fee.rs b/zk-token-sdk/src/instruction/transfer_with_fee.rs index 45a9496d63..213d9356f2 100644 --- a/zk-token-sdk/src/instruction/transfer_with_fee.rs +++ b/zk-token-sdk/src/instruction/transfer_with_fee.rs @@ -20,6 +20,7 @@ use { transcript::TranscriptProtocol, }, arrayref::{array_ref, array_refs}, + bytemuck::bytes_of, curve25519_dalek::scalar::Scalar, merlin::Transcript, std::convert::TryInto, @@ -62,7 +63,7 @@ lazy_static::lazy_static! { /// The instruction data that is needed for the `ProofInstruction::TransferWithFee` instruction. /// -/// It includes the cryptographic proof as well as the cotnext data information needed to verify +/// It includes the cryptographic proof as well as the context data information needed to verify /// the proof. #[derive(Clone, Copy, Pod, Zeroable)] #[repr(C)] @@ -197,14 +198,7 @@ impl TransferWithFeeData { fee_parameters: fee_parameters.into(), }; - let mut transcript = TransferWithFeeProof::transcript_new( - &pod_transfer_with_fee_pubkeys, - &pod_ciphertext_lo, - &pod_ciphertext_hi, - &pod_new_source_ciphertext, - &pod_fee_ciphertext_lo, - &pod_fee_ciphertext_hi, - ); + let mut transcript = context.new_transcript(); let proof = TransferWithFeeProof::new( (amount_lo, &ciphertext_lo, &opening_lo), @@ -353,14 +347,7 @@ impl ZkProofData for TransferWithFeeData { #[cfg(not(target_os = "solana"))] fn verify_proof(&self) -> Result<(), ProofError> { - let mut transcript = TransferWithFeeProof::transcript_new( - &self.context.transfer_with_fee_pubkeys, - &self.context.ciphertext_lo, - &self.context.ciphertext_hi, - &self.context.new_source_ciphertext, - &self.context.fee_ciphertext_lo, - &self.context.fee_ciphertext_hi, - ); + let mut transcript = self.context.new_transcript(); let ciphertext_lo = self.context.ciphertext_lo.try_into()?; let ciphertext_hi = self.context.ciphertext_hi.try_into()?; @@ -384,7 +371,28 @@ impl ZkProofData for TransferWithFeeData { } } -// #[derive(Clone, Copy, Pod, Zeroable)] +#[allow(non_snake_case)] +#[cfg(not(target_os = "solana"))] +impl TransferWithFeeProofContext { + fn new_transcript(&self) -> Transcript { + let mut transcript = Transcript::new(b"transfer-with-fee-proof"); + transcript.append_message(b"ciphertext-lo", bytes_of(&self.ciphertext_lo)); + transcript.append_message(b"ciphertext-hi", bytes_of(&self.ciphertext_hi)); + transcript.append_message( + b"transfer-with-fee-pubkeys", + bytes_of(&self.transfer_with_fee_pubkeys), + ); + transcript.append_message( + b"new-source-ciphertext", + bytes_of(&self.new_source_ciphertext), + ); + transcript.append_message(b"fee-ciphertext-lo", bytes_of(&self.fee_ciphertext_lo)); + transcript.append_message(b"fee-ciphertext-hi", bytes_of(&self.fee_ciphertext_hi)); + transcript.append_message(b"fee-parameters", bytes_of(&self.fee_parameters)); + transcript + } +} + #[repr(C)] #[derive(Clone, Copy, Pod, Zeroable)] pub struct TransferWithFeeProof { @@ -400,56 +408,6 @@ pub struct TransferWithFeeProof { #[allow(non_snake_case)] #[cfg(not(target_os = "solana"))] impl TransferWithFeeProof { - fn transcript_new( - transfer_with_fee_pubkeys: &pod::TransferWithFeePubkeys, - ciphertext_lo: &pod::TransferAmountEncryption, - ciphertext_hi: &pod::TransferAmountEncryption, - new_source_ciphertext: &pod::ElGamalCiphertext, - fee_ciphertext_lo: &pod::FeeEncryption, - fee_ciphertext_hi: &pod::FeeEncryption, - ) -> Transcript { - let mut transcript = Transcript::new(b"FeeProof"); - - transcript.append_pubkey(b"pubkey-source", &transfer_with_fee_pubkeys.source_pubkey); - transcript.append_pubkey( - b"pubkey-dest", - &transfer_with_fee_pubkeys.destination_pubkey, - ); - transcript.append_pubkey(b"pubkey-auditor", &transfer_with_fee_pubkeys.auditor_pubkey); - transcript.append_pubkey( - b"withdraw_withheld_authority_pubkey", - &transfer_with_fee_pubkeys.withdraw_withheld_authority_pubkey, - ); - - transcript.append_commitment(b"comm-lo-amount", &ciphertext_lo.commitment); - transcript.append_handle(b"handle-lo-source", &ciphertext_lo.source_handle); - transcript.append_handle(b"handle-lo-dest", &ciphertext_lo.destination_handle); - transcript.append_handle(b"handle-lo-auditor", &ciphertext_lo.auditor_handle); - - transcript.append_commitment(b"comm-hi-amount", &ciphertext_hi.commitment); - transcript.append_handle(b"handle-hi-source", &ciphertext_hi.source_handle); - transcript.append_handle(b"handle-hi-dest", &ciphertext_hi.destination_handle); - transcript.append_handle(b"handle-hi-auditor", &ciphertext_hi.auditor_handle); - - transcript.append_ciphertext(b"ctxt-new-source", new_source_ciphertext); - - transcript.append_commitment(b"comm-fee-lo", &fee_ciphertext_lo.commitment); - transcript.append_handle(b"handle-fee-lo-dest", &fee_ciphertext_lo.destination_handle); - transcript.append_handle( - b"handle-fee-lo-auditor", - &fee_ciphertext_lo.withdraw_withheld_authority_handle, - ); - - transcript.append_commitment(b"comm-fee-hi", &fee_ciphertext_hi.commitment); - transcript.append_handle(b"handle-fee-hi-dest", &fee_ciphertext_hi.destination_handle); - transcript.append_handle( - b"handle-fee-hi-auditor", - &fee_ciphertext_hi.withdraw_withheld_authority_handle, - ); - - transcript - } - #[allow(clippy::too_many_arguments)] #[allow(clippy::many_single_char_names)] pub fn new( diff --git a/zk-token-sdk/src/instruction/withdraw.rs b/zk-token-sdk/src/instruction/withdraw.rs index 009cd95020..2ddd1462b0 100644 --- a/zk-token-sdk/src/instruction/withdraw.rs +++ b/zk-token-sdk/src/instruction/withdraw.rs @@ -77,7 +77,7 @@ impl WithdrawData { final_ciphertext: pod_final_ciphertext, }; - let mut transcript = WithdrawProof::transcript_new(&pod_pubkey, &pod_final_ciphertext); + let mut transcript = context.new_transcript(); let proof = WithdrawProof::new(keypair, final_balance, &final_ciphertext, &mut transcript); Ok(Self { context, proof }) @@ -93,8 +93,7 @@ impl ZkProofData for WithdrawData { #[cfg(not(target_os = "solana"))] fn verify_proof(&self) -> Result<(), ProofError> { - let mut transcript = - WithdrawProof::transcript_new(&self.context.pubkey, &self.context.final_ciphertext); + let mut transcript = self.context.new_transcript(); let elgamal_pubkey = self.context.pubkey.try_into()?; let final_balance_ciphertext = self.context.final_ciphertext.try_into()?; @@ -103,6 +102,19 @@ impl ZkProofData for WithdrawData { } } +#[allow(non_snake_case)] +#[cfg(not(target_os = "solana"))] +impl WithdrawProofContext { + fn new_transcript(&self) -> Transcript { + let mut transcript = Transcript::new(b"WithdrawProof"); + + transcript.append_pubkey(b"pubkey", &self.pubkey); + transcript.append_ciphertext(b"ciphertext", &self.final_ciphertext); + + transcript + } +} + /// The withdraw proof. /// /// It contains a ciphertext-commitment equality proof and a 64-bit range proof. @@ -123,18 +135,6 @@ pub struct WithdrawProof { #[allow(non_snake_case)] #[cfg(not(target_os = "solana"))] impl WithdrawProof { - fn transcript_new( - pubkey: &pod::ElGamalPubkey, - ciphertext: &pod::ElGamalCiphertext, - ) -> Transcript { - let mut transcript = Transcript::new(b"WithdrawProof"); - - transcript.append_pubkey(b"pubkey", pubkey); - transcript.append_ciphertext(b"ciphertext", ciphertext); - - transcript - } - pub fn new( keypair: &ElGamalKeypair, final_balance: u64, diff --git a/zk-token-sdk/src/instruction/zero_balance.rs b/zk-token-sdk/src/instruction/zero_balance.rs index 0d676cb131..672ada7d9b 100644 --- a/zk-token-sdk/src/instruction/zero_balance.rs +++ b/zk-token-sdk/src/instruction/zero_balance.rs @@ -62,7 +62,7 @@ impl ZeroBalanceProofData { ciphertext: pod_ciphertext, }; - let mut transcript = ZeroBalanceProof::transcript_new(&pod_pubkey, &pod_ciphertext); + let mut transcript = context.new_transcript(); let proof = ZeroBalanceProof::new(keypair, ciphertext, &mut transcript).into(); Ok(ZeroBalanceProofData { context, proof }) @@ -78,9 +78,7 @@ impl ZkProofData for ZeroBalanceProofData { #[cfg(not(target_os = "solana"))] fn verify_proof(&self) -> Result<(), ProofError> { - let mut transcript = - ZeroBalanceProof::transcript_new(&self.context.pubkey, &self.context.ciphertext); - + let mut transcript = self.context.new_transcript(); let pubkey = self.context.pubkey.try_into()?; let ciphertext = self.context.ciphertext.try_into()?; let proof: ZeroBalanceProof = self.proof.try_into()?; @@ -92,15 +90,12 @@ impl ZkProofData for ZeroBalanceProofData { #[allow(non_snake_case)] #[cfg(not(target_os = "solana"))] -impl ZeroBalanceProof { - fn transcript_new( - pubkey: &pod::ElGamalPubkey, - ciphertext: &pod::ElGamalCiphertext, - ) -> Transcript { +impl ZeroBalanceProofContext { + fn new_transcript(&self) -> Transcript { let mut transcript = Transcript::new(b"ZeroBalanceProof"); - transcript.append_pubkey(b"pubkey", pubkey); - transcript.append_ciphertext(b"ciphertext", ciphertext); + transcript.append_pubkey(b"pubkey", &self.pubkey); + transcript.append_ciphertext(b"ciphertext", &self.ciphertext); transcript }