[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 <joncinque@pm.me>

* Update zk-token-sdk/src/instruction/transfer.rs

Co-authored-by: Jon Cinque <joncinque@pm.me>

---------

Co-authored-by: Jon Cinque <joncinque@pm.me>
This commit is contained in:
samkim-crypto 2023-05-20 07:08:40 +09:00 committed by GitHub
parent 359eaad4e7
commit 4796e2fd84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 162 deletions

View File

@ -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<CiphertextCiphertextEqualityProofContext>
#[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<CiphertextCiphertextEqualityProofContext>
#[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
}

View File

@ -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<PubkeyValidityProofContext> 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<PubkeyValidityProofContext> 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
}
}

View File

@ -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<TransferProofContext> 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<TransferProofContext> 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,

View File

@ -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<TransferWithFeeProofContext> 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<TransferWithFeeProofContext> 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(

View File

@ -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<WithdrawProofContext> 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<WithdrawProofContext> 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,

View File

@ -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<ZeroBalanceProofContext> 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<ZeroBalanceProofContext> 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
}