Skip to content

Commit

Permalink
v1.16: [zk-token-sdk] rename TransferAmountEncryption to `TransferA…
Browse files Browse the repository at this point in the history
…mountCiphertext` and define it as a wrapper around `GroupedElGamalCiphertext` (backport of #32026) (#32092)

[zk-token-sdk] rename `TransferAmountEncryption` to `TransferAmountCiphertext` and define it as a wrapper around `GroupedElGamalCiphertext` (#32026)

* define `TransferAmountEncryption` as a wrapper around `GroupedElGamalCiphertext`

* implement `From<GroupedElGamalCiphertext<3>>` for `GroupedElGamalCiphertext3Handles`

* define pod `TransferAmountEncryption` as a wrapper around pod `GroupedElGamalCiphertext3Handles`

* derive `Copy`, `Debug`, `Eq`, and `PartialEq` traits for `TransferAmountEncryption`

* rename `TransferAmountEncryption` to `TransferAmountCiphertext`

* clippy

* fix target arch

* add comment on why it is safe to unwrap

(cherry picked from commit c10d3d1)

Co-authored-by: samkim-crypto <skim13@cs.stanford.edu>
  • Loading branch information
mergify[bot] and samkim-crypto committed Jun 13, 2023
1 parent def781a commit 042bd60
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 130 deletions.
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 @@ -81,10 +81,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 @@ -115,13 +115,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 @@ -134,13 +134,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 @@ -183,8 +183,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 @@ -220,19 +220,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 @@ -241,19 +241,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 @@ -412,8 +412,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 @@ -457,8 +457,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 @@ -550,8 +550,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 @@ -587,21 +587,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 @@ -653,8 +659,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

0 comments on commit 042bd60

Please sign in to comment.