Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

v1.16: [zk-token-sdk] rename TransferAmountEncryption to TransferAmountCiphertext and define it as a wrapper around GroupedElGamalCiphertext (backport of #32026) #32092

Merged
merged 1 commit into from
Jun 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 31 additions & 24 deletions zk-token-sdk/src/instruction/transfer/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,55 @@
use crate::{
encryption::{
elgamal::{DecryptHandle, ElGamalPubkey},
grouped_elgamal::{GroupedElGamal, GroupedElGamalCiphertext},
pedersen::{Pedersen, PedersenCommitment, PedersenOpening},
},
zk_token_elgamal::pod,
};

// TransferAmountEncryption
#[derive(Clone)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(C)]
#[cfg(not(target_os = "solana"))]
pub struct TransferAmountEncryption {
pub commitment: PedersenCommitment,
pub source_handle: DecryptHandle,
pub destination_handle: DecryptHandle,
pub auditor_handle: DecryptHandle,
}
pub struct TransferAmountCiphertext(pub(crate) GroupedElGamalCiphertext<3>);

#[cfg(not(target_os = "solana"))]
impl TransferAmountEncryption {
impl TransferAmountCiphertext {
pub fn new(
amount: u64,
source_pubkey: &ElGamalPubkey,
destination_pubkey: &ElGamalPubkey,
auditor_pubkey: &ElGamalPubkey,
) -> (Self, PedersenOpening) {
let (commitment, opening) = Pedersen::new(amount);
let transfer_amount_encryption = Self {
commitment,
source_handle: source_pubkey.decrypt_handle(&opening),
destination_handle: destination_pubkey.decrypt_handle(&opening),
auditor_handle: auditor_pubkey.decrypt_handle(&opening),
};
let opening = PedersenOpening::new_rand();
let grouped_ciphertext = GroupedElGamal::<3>::encrypt_with(
[source_pubkey, destination_pubkey, auditor_pubkey],
amount,
&opening,
);

(transfer_amount_encryption, opening)
(Self(grouped_ciphertext), opening)
}

pub fn to_pod(&self) -> pod::TransferAmountEncryption {
pod::TransferAmountEncryption {
commitment: self.commitment.into(),
source_handle: self.source_handle.into(),
destination_handle: self.destination_handle.into(),
auditor_handle: self.auditor_handle.into(),
}
pub fn get_commitment(&self) -> &PedersenCommitment {
&self.0.commitment
}

pub fn get_source_handle(&self) -> &DecryptHandle {
// `TransferAmountCiphertext` is a wrapper for `GroupedElGamalCiphertext<3>`, which
// holds exactly three decryption handles.
self.0.handles.get(0).unwrap()
}

pub fn get_destination_handle(&self) -> &DecryptHandle {
// `TransferAmountCiphertext` is a wrapper for `GroupedElGamalCiphertext<3>`, which holds
// exactly three decryption handles.
self.0.handles.get(1).unwrap()
}

pub fn get_auditor_handle(&self) -> &DecryptHandle {
// `TransferAmountCiphertext` is a wrapper for `GroupedElGamalCiphertext<3>`, which holds
// exactly three decryption handles.
self.0.handles.get(2).unwrap()
}
}

Expand Down
2 changes: 1 addition & 1 deletion zk-token-sdk/src/instruction/transfer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use {
};
#[cfg(not(target_os = "solana"))]
pub use {
encryption::{FeeEncryption, TransferAmountEncryption},
encryption::{FeeEncryption, TransferAmountCiphertext},
with_fee::TransferWithFeePubkeys,
without_fee::TransferPubkeys,
};
Expand Down
80 changes: 43 additions & 37 deletions zk-token-sdk/src/instruction/transfer/with_fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use {
instruction::transfer::{
combine_lo_hi_ciphertexts, combine_lo_hi_commitments, combine_lo_hi_openings,
combine_lo_hi_u64,
encryption::{FeeEncryption, TransferAmountEncryption},
encryption::{FeeEncryption, TransferAmountCiphertext},
split_u64, FeeParameters, Role,
},
range_proof::RangeProof,
Expand Down Expand Up @@ -80,10 +80,10 @@ pub struct TransferWithFeeData {
#[repr(C)]
pub struct TransferWithFeeProofContext {
/// Group encryption of the low 16 bites of the transfer amount
pub ciphertext_lo: pod::TransferAmountEncryption, // 128 bytes
pub ciphertext_lo: pod::TransferAmountCiphertext, // 128 bytes

/// Group encryption of the high 48 bits of the transfer amount
pub ciphertext_hi: pod::TransferAmountEncryption, // 128 bytes
pub ciphertext_hi: pod::TransferAmountCiphertext, // 128 bytes

/// The public encryption keys associated with the transfer: source, dest, and auditor
pub transfer_with_fee_pubkeys: pod::TransferWithFeePubkeys, // 128 bytes
Expand Down Expand Up @@ -114,13 +114,13 @@ impl TransferWithFeeData {
// split and encrypt transfer amount
let (amount_lo, amount_hi) = split_u64(transfer_amount, TRANSFER_AMOUNT_LO_BITS);

let (ciphertext_lo, opening_lo) = TransferAmountEncryption::new(
let (ciphertext_lo, opening_lo) = TransferAmountCiphertext::new(
amount_lo,
&source_keypair.public,
destination_pubkey,
auditor_pubkey,
);
let (ciphertext_hi, opening_hi) = TransferAmountEncryption::new(
let (ciphertext_hi, opening_hi) = TransferAmountCiphertext::new(
amount_hi,
&source_keypair.public,
destination_pubkey,
Expand All @@ -133,13 +133,13 @@ impl TransferWithFeeData {
.ok_or(ProofError::Generation)?;

let transfer_amount_lo_source = ElGamalCiphertext {
commitment: ciphertext_lo.commitment,
handle: ciphertext_lo.source_handle,
commitment: *ciphertext_lo.get_commitment(),
handle: *ciphertext_lo.get_source_handle(),
};

let transfer_amount_hi_source = ElGamalCiphertext {
commitment: ciphertext_hi.commitment,
handle: ciphertext_hi.source_handle,
commitment: *ciphertext_hi.get_commitment(),
handle: *ciphertext_hi.get_source_handle(),
};

let new_source_ciphertext = old_source_ciphertext
Expand Down Expand Up @@ -182,8 +182,8 @@ impl TransferWithFeeData {
auditor_pubkey: (*auditor_pubkey).into(),
withdraw_withheld_authority_pubkey: (*withdraw_withheld_authority_pubkey).into(),
};
let pod_ciphertext_lo: pod::TransferAmountEncryption = ciphertext_lo.to_pod();
let pod_ciphertext_hi: pod::TransferAmountEncryption = ciphertext_hi.to_pod();
let pod_ciphertext_lo: pod::TransferAmountCiphertext = ciphertext_lo.into();
let pod_ciphertext_hi: pod::TransferAmountCiphertext = ciphertext_hi.into();
let pod_new_source_ciphertext: pod::ElGamalCiphertext = new_source_ciphertext.into();
let pod_fee_ciphertext_lo: pod::FeeEncryption = fee_ciphertext_lo.to_pod();
let pod_fee_ciphertext_hi: pod::FeeEncryption = fee_ciphertext_hi.to_pod();
Expand Down Expand Up @@ -219,19 +219,19 @@ impl TransferWithFeeData {

/// Extracts the lo ciphertexts associated with a transfer-with-fee data
fn ciphertext_lo(&self, role: Role) -> Result<ElGamalCiphertext, ProofError> {
let ciphertext_lo: TransferAmountEncryption = self.context.ciphertext_lo.try_into()?;
let ciphertext_lo: TransferAmountCiphertext = self.context.ciphertext_lo.try_into()?;

let handle_lo = match role {
Role::Source => Some(ciphertext_lo.source_handle),
Role::Destination => Some(ciphertext_lo.destination_handle),
Role::Auditor => Some(ciphertext_lo.auditor_handle),
Role::Source => Some(ciphertext_lo.get_source_handle()),
Role::Destination => Some(ciphertext_lo.get_destination_handle()),
Role::Auditor => Some(ciphertext_lo.get_auditor_handle()),
Role::WithdrawWithheldAuthority => None,
};

if let Some(handle) = handle_lo {
Ok(ElGamalCiphertext {
commitment: ciphertext_lo.commitment,
handle,
commitment: *ciphertext_lo.get_commitment(),
handle: *handle,
})
} else {
Err(ProofError::MissingCiphertext)
Expand All @@ -240,19 +240,19 @@ impl TransferWithFeeData {

/// Extracts the lo ciphertexts associated with a transfer-with-fee data
fn ciphertext_hi(&self, role: Role) -> Result<ElGamalCiphertext, ProofError> {
let ciphertext_hi: TransferAmountEncryption = self.context.ciphertext_hi.try_into()?;
let ciphertext_hi: TransferAmountCiphertext = self.context.ciphertext_hi.try_into()?;

let handle_hi = match role {
Role::Source => Some(ciphertext_hi.source_handle),
Role::Destination => Some(ciphertext_hi.destination_handle),
Role::Auditor => Some(ciphertext_hi.auditor_handle),
Role::Source => Some(ciphertext_hi.get_source_handle()),
Role::Destination => Some(ciphertext_hi.get_destination_handle()),
Role::Auditor => Some(ciphertext_hi.get_auditor_handle()),
Role::WithdrawWithheldAuthority => None,
};

if let Some(handle) = handle_hi {
Ok(ElGamalCiphertext {
commitment: ciphertext_hi.commitment,
handle,
commitment: *ciphertext_hi.get_commitment(),
handle: *handle,
})
} else {
Err(ProofError::MissingCiphertext)
Expand Down Expand Up @@ -411,8 +411,8 @@ impl TransferWithFeeProof {
#[allow(clippy::too_many_arguments)]
#[allow(clippy::many_single_char_names)]
pub fn new(
transfer_amount_lo_data: (u64, &TransferAmountEncryption, &PedersenOpening),
transfer_amount_hi_data: (u64, &TransferAmountEncryption, &PedersenOpening),
transfer_amount_lo_data: (u64, &TransferAmountCiphertext, &PedersenOpening),
transfer_amount_hi_data: (u64, &TransferAmountCiphertext, &PedersenOpening),
source_keypair: &ElGamalKeypair,
(destination_pubkey, auditor_pubkey): (&ElGamalPubkey, &ElGamalPubkey),
(source_new_balance, new_source_ciphertext): (u64, &ElGamalCiphertext),
Expand Down Expand Up @@ -456,8 +456,8 @@ impl TransferWithFeeProof {
transcript.append_commitment(b"commitment-claimed", &pod_claimed_commitment);

let combined_commitment = combine_lo_hi_commitments(
&ciphertext_lo.commitment,
&ciphertext_hi.commitment,
ciphertext_lo.get_commitment(),
ciphertext_hi.get_commitment(),
TRANSFER_AMOUNT_LO_BITS,
);
let combined_opening =
Expand Down Expand Up @@ -549,8 +549,8 @@ impl TransferWithFeeProof {

pub fn verify(
&self,
ciphertext_lo: &TransferAmountEncryption,
ciphertext_hi: &TransferAmountEncryption,
ciphertext_lo: &TransferAmountCiphertext,
ciphertext_hi: &TransferAmountCiphertext,
transfer_with_fee_pubkeys: &TransferWithFeePubkeys,
new_spendable_ciphertext: &ElGamalCiphertext,
// fee parameters
Expand Down Expand Up @@ -586,21 +586,27 @@ impl TransferWithFeeProof {
&transfer_with_fee_pubkeys.destination_pubkey,
&transfer_with_fee_pubkeys.auditor_pubkey,
),
(&ciphertext_lo.commitment, &ciphertext_hi.commitment),
(
&ciphertext_lo.destination_handle,
&ciphertext_hi.destination_handle,
ciphertext_lo.get_commitment(),
ciphertext_hi.get_commitment(),
),
(
ciphertext_lo.get_destination_handle(),
ciphertext_hi.get_destination_handle(),
),
(
ciphertext_lo.get_auditor_handle(),
ciphertext_hi.get_auditor_handle(),
),
(&ciphertext_lo.auditor_handle, &ciphertext_hi.auditor_handle),
transcript,
)?;

// verify fee sigma proof
transcript.append_commitment(b"commitment-claimed", &self.claimed_commitment);

let combined_commitment = combine_lo_hi_commitments(
&ciphertext_lo.commitment,
&ciphertext_hi.commitment,
ciphertext_lo.get_commitment(),
ciphertext_hi.get_commitment(),
TRANSFER_AMOUNT_LO_BITS,
);
let combined_fee_commitment = combine_lo_hi_commitments(
Expand Down Expand Up @@ -652,8 +658,8 @@ impl TransferWithFeeProof {
range_proof.verify(
vec![
&new_source_commitment,
&ciphertext_lo.commitment,
&ciphertext_hi.commitment,
ciphertext_lo.get_commitment(),
ciphertext_hi.get_commitment(),
&claimed_commitment,
&claimed_commitment_negated,
&fee_ciphertext_lo.commitment,
Expand Down