[zk-token-sdk] remove non-pod structs `TransferPubkeys` and `TransferWithFeePubkeys` (#32042)

* remove decoded `TransferWithFeePubkeys`

* remove decoded `TransferPubkey`

* rename `TransferPubkeys` and `TransferWithFeePubkeys` fields

* relocate `TransferPubkeys` and `TransferWithFeePubkeys`

* reorder proof verify parameters for transfer and transfer with fee

* clippy
This commit is contained in:
samkim-crypto 2023-06-20 07:07:30 +09:00 committed by GitHub
parent 748223c928
commit d654715adf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 71 additions and 195 deletions

View File

@ -20,7 +20,6 @@ use {
}, },
transcript::TranscriptProtocol, transcript::TranscriptProtocol,
}, },
arrayref::{array_ref, array_refs},
bytemuck::bytes_of, bytemuck::bytes_of,
curve25519_dalek::scalar::Scalar, curve25519_dalek::scalar::Scalar,
merlin::Transcript, merlin::Transcript,
@ -87,7 +86,7 @@ pub struct TransferWithFeeProofContext {
pub ciphertext_hi: pod::TransferAmountCiphertext, // 128 bytes pub ciphertext_hi: pod::TransferAmountCiphertext, // 128 bytes
/// The public encryption keys associated with the transfer: source, dest, and auditor /// The public encryption keys associated with the transfer: source, dest, and auditor
pub transfer_with_fee_pubkeys: pod::TransferWithFeePubkeys, // 128 bytes pub transfer_with_fee_pubkeys: TransferWithFeePubkeys, // 128 bytes
/// The final spendable ciphertext after the transfer, /// The final spendable ciphertext after the transfer,
pub new_source_ciphertext: pod::ElGamalCiphertext, // 64 bytes pub new_source_ciphertext: pod::ElGamalCiphertext, // 64 bytes
@ -102,6 +101,16 @@ pub struct TransferWithFeeProofContext {
pub fee_parameters: pod::FeeParameters, // 10 bytes pub fee_parameters: pod::FeeParameters, // 10 bytes
} }
/// The ElGamal public keys needed for a transfer with fee
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
pub struct TransferWithFeePubkeys {
pub source: pod::ElGamalPubkey,
pub destination: pod::ElGamalPubkey,
pub auditor: pod::ElGamalPubkey,
pub withdraw_withheld_authority: pod::ElGamalPubkey,
}
#[cfg(not(target_os = "solana"))] #[cfg(not(target_os = "solana"))]
impl TransferWithFeeData { impl TransferWithFeeData {
pub fn new( pub fn new(
@ -177,11 +186,11 @@ impl TransferWithFeeData {
); );
// generate transcript and append all public inputs // generate transcript and append all public inputs
let pod_transfer_with_fee_pubkeys = pod::TransferWithFeePubkeys { let pod_transfer_with_fee_pubkeys = TransferWithFeePubkeys {
source_pubkey: source_keypair.public.into(), source: source_keypair.public.into(),
destination_pubkey: (*destination_pubkey).into(), destination: (*destination_pubkey).into(),
auditor_pubkey: (*auditor_pubkey).into(), auditor: (*auditor_pubkey).into(),
withdraw_withheld_authority_pubkey: (*withdraw_withheld_authority_pubkey).into(), withdraw_withheld_authority: (*withdraw_withheld_authority_pubkey).into(),
}; };
let pod_ciphertext_lo: pod::TransferAmountCiphertext = ciphertext_lo.into(); let pod_ciphertext_lo: pod::TransferAmountCiphertext = ciphertext_lo.into();
let pod_ciphertext_hi: pod::TransferAmountCiphertext = ciphertext_hi.into(); let pod_ciphertext_hi: pod::TransferAmountCiphertext = ciphertext_hi.into();
@ -350,9 +359,21 @@ impl ZkProofData<TransferWithFeeProofContext> for TransferWithFeeData {
fn verify_proof(&self) -> Result<(), ProofError> { fn verify_proof(&self) -> Result<(), ProofError> {
let mut transcript = self.context.new_transcript(); let mut transcript = self.context.new_transcript();
let source_pubkey = self.context.transfer_with_fee_pubkeys.source.try_into()?;
let destination_pubkey = self
.context
.transfer_with_fee_pubkeys
.destination
.try_into()?;
let auditor_pubkey = self.context.transfer_with_fee_pubkeys.auditor.try_into()?;
let withdraw_withheld_authority_pubkey = self
.context
.transfer_with_fee_pubkeys
.withdraw_withheld_authority
.try_into()?;
let ciphertext_lo = self.context.ciphertext_lo.try_into()?; let ciphertext_lo = self.context.ciphertext_lo.try_into()?;
let ciphertext_hi = self.context.ciphertext_hi.try_into()?; let ciphertext_hi = self.context.ciphertext_hi.try_into()?;
let pubkeys_transfer_with_fee = self.context.transfer_with_fee_pubkeys.try_into()?;
let new_source_ciphertext = self.context.new_source_ciphertext.try_into()?; let new_source_ciphertext = self.context.new_source_ciphertext.try_into()?;
let fee_ciphertext_lo = self.context.fee_ciphertext_lo.try_into()?; let fee_ciphertext_lo = self.context.fee_ciphertext_lo.try_into()?;
@ -360,9 +381,12 @@ impl ZkProofData<TransferWithFeeProofContext> for TransferWithFeeData {
let fee_parameters = self.context.fee_parameters.into(); let fee_parameters = self.context.fee_parameters.into();
self.proof.verify( self.proof.verify(
&source_pubkey,
&destination_pubkey,
&auditor_pubkey,
&withdraw_withheld_authority_pubkey,
&ciphertext_lo, &ciphertext_lo,
&ciphertext_hi, &ciphertext_hi,
&pubkeys_transfer_with_fee,
&new_source_ciphertext, &new_source_ciphertext,
&fee_ciphertext_lo, &fee_ciphertext_lo,
&fee_ciphertext_hi, &fee_ciphertext_hi,
@ -548,11 +572,15 @@ impl TransferWithFeeProof {
} }
} }
#[allow(clippy::too_many_arguments)]
pub fn verify( pub fn verify(
&self, &self,
source_pubkey: &ElGamalPubkey,
destination_pubkey: &ElGamalPubkey,
auditor_pubkey: &ElGamalPubkey,
withdraw_withheld_authority_pubkey: &ElGamalPubkey,
ciphertext_lo: &TransferAmountCiphertext, ciphertext_lo: &TransferAmountCiphertext,
ciphertext_hi: &TransferAmountCiphertext, ciphertext_hi: &TransferAmountCiphertext,
transfer_with_fee_pubkeys: &TransferWithFeePubkeys,
new_spendable_ciphertext: &ElGamalCiphertext, new_spendable_ciphertext: &ElGamalCiphertext,
// fee parameters // fee parameters
fee_ciphertext_lo: &FeeEncryption, fee_ciphertext_lo: &FeeEncryption,
@ -575,7 +603,7 @@ impl TransferWithFeeProof {
// verify equality proof // verify equality proof
equality_proof.verify( equality_proof.verify(
&transfer_with_fee_pubkeys.source_pubkey, source_pubkey,
new_spendable_ciphertext, new_spendable_ciphertext,
&new_source_commitment, &new_source_commitment,
transcript, transcript,
@ -583,10 +611,7 @@ impl TransferWithFeeProof {
// verify that the transfer amount is encrypted correctly // verify that the transfer amount is encrypted correctly
ciphertext_amount_validity_proof.verify( ciphertext_amount_validity_proof.verify(
( (destination_pubkey, auditor_pubkey),
&transfer_with_fee_pubkeys.destination_pubkey,
&transfer_with_fee_pubkeys.auditor_pubkey,
),
( (
ciphertext_lo.get_commitment(), ciphertext_lo.get_commitment(),
ciphertext_hi.get_commitment(), ciphertext_hi.get_commitment(),
@ -636,10 +661,7 @@ impl TransferWithFeeProof {
// verify ciphertext validity proof for fee ciphertexts // verify ciphertext validity proof for fee ciphertexts
fee_ciphertext_validity_proof.verify( fee_ciphertext_validity_proof.verify(
( (destination_pubkey, withdraw_withheld_authority_pubkey),
&transfer_with_fee_pubkeys.destination_pubkey,
&transfer_with_fee_pubkeys.withdraw_withheld_authority_pubkey,
),
( (
fee_ciphertext_lo.get_commitment(), fee_ciphertext_lo.get_commitment(),
fee_ciphertext_hi.get_commitment(), fee_ciphertext_hi.get_commitment(),
@ -685,52 +707,6 @@ impl TransferWithFeeProof {
} }
} }
/// The ElGamal public keys needed for a transfer with fee
#[derive(Clone)]
#[repr(C)]
#[cfg(not(target_os = "solana"))]
pub struct TransferWithFeePubkeys {
pub source_pubkey: ElGamalPubkey,
pub destination_pubkey: ElGamalPubkey,
pub auditor_pubkey: ElGamalPubkey,
pub withdraw_withheld_authority_pubkey: ElGamalPubkey,
}
#[cfg(not(target_os = "solana"))]
impl TransferWithFeePubkeys {
pub fn to_bytes(&self) -> [u8; 128] {
let mut bytes = [0u8; 128];
bytes[..32].copy_from_slice(&self.source_pubkey.to_bytes());
bytes[32..64].copy_from_slice(&self.destination_pubkey.to_bytes());
bytes[64..96].copy_from_slice(&self.auditor_pubkey.to_bytes());
bytes[96..128].copy_from_slice(&self.withdraw_withheld_authority_pubkey.to_bytes());
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ProofError> {
let bytes = array_ref![bytes, 0, 128];
let (source_pubkey, destination_pubkey, auditor_pubkey, withdraw_withheld_authority_pubkey) =
array_refs![bytes, 32, 32, 32, 32];
let source_pubkey =
ElGamalPubkey::from_bytes(source_pubkey).ok_or(ProofError::PubkeyDeserialization)?;
let destination_pubkey = ElGamalPubkey::from_bytes(destination_pubkey)
.ok_or(ProofError::PubkeyDeserialization)?;
let auditor_pubkey =
ElGamalPubkey::from_bytes(auditor_pubkey).ok_or(ProofError::PubkeyDeserialization)?;
let withdraw_withheld_authority_pubkey =
ElGamalPubkey::from_bytes(withdraw_withheld_authority_pubkey)
.ok_or(ProofError::PubkeyDeserialization)?;
Ok(Self {
source_pubkey,
destination_pubkey,
auditor_pubkey,
withdraw_withheld_authority_pubkey,
})
}
}
#[cfg(not(target_os = "solana"))] #[cfg(not(target_os = "solana"))]
fn calculate_fee(transfer_amount: u64, fee_rate_basis_points: u16) -> Option<(u64, u64)> { fn calculate_fee(transfer_amount: u64, fee_rate_basis_points: u16) -> Option<(u64, u64)> {
let numerator = (transfer_amount as u128).checked_mul(fee_rate_basis_points as u128)?; let numerator = (transfer_amount as u128).checked_mul(fee_rate_basis_points as u128)?;

View File

@ -16,7 +16,6 @@ use {
}, },
transcript::TranscriptProtocol, transcript::TranscriptProtocol,
}, },
arrayref::{array_ref, array_refs},
bytemuck::bytes_of, bytemuck::bytes_of,
merlin::Transcript, merlin::Transcript,
std::convert::TryInto, std::convert::TryInto,
@ -69,12 +68,21 @@ pub struct TransferProofContext {
pub ciphertext_hi: pod::TransferAmountCiphertext, // 128 bytes pub ciphertext_hi: pod::TransferAmountCiphertext, // 128 bytes
/// The public encryption keys associated with the transfer: source, dest, and auditor /// The public encryption keys associated with the transfer: source, dest, and auditor
pub transfer_pubkeys: pod::TransferPubkeys, // 96 bytes pub transfer_pubkeys: TransferPubkeys, // 96 bytes
/// The final spendable ciphertext after the transfer /// The final spendable ciphertext after the transfer
pub new_source_ciphertext: pod::ElGamalCiphertext, // 64 bytes pub new_source_ciphertext: pod::ElGamalCiphertext, // 64 bytes
} }
/// The ElGamal public keys needed for a transfer
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
pub struct TransferPubkeys {
pub source: pod::ElGamalPubkey,
pub destination: pod::ElGamalPubkey,
pub auditor: pod::ElGamalPubkey,
}
#[cfg(not(target_os = "solana"))] #[cfg(not(target_os = "solana"))]
impl TransferData { impl TransferData {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@ -124,10 +132,10 @@ impl TransferData {
); );
// generate transcript and append all public inputs // generate transcript and append all public inputs
let pod_transfer_pubkeys = pod::TransferPubkeys { let pod_transfer_pubkeys = TransferPubkeys {
source_pubkey: source_keypair.public.into(), source: source_keypair.public.into(),
destination_pubkey: (*destination_pubkey).into(), destination: (*destination_pubkey).into(),
auditor_pubkey: (*auditor_pubkey).into(), auditor: (*auditor_pubkey).into(),
}; };
let pod_ciphertext_lo: pod::TransferAmountCiphertext = ciphertext_lo.into(); let pod_ciphertext_lo: pod::TransferAmountCiphertext = ciphertext_lo.into();
let pod_ciphertext_hi: pod::TransferAmountCiphertext = ciphertext_hi.into(); let pod_ciphertext_hi: pod::TransferAmountCiphertext = ciphertext_hi.into();
@ -225,15 +233,20 @@ impl ZkProofData<TransferProofContext> for TransferData {
// generate transcript and append all public inputs // generate transcript and append all public inputs
let mut transcript = self.context.new_transcript(); let mut transcript = self.context.new_transcript();
let source_pubkey = self.context.transfer_pubkeys.source.try_into()?;
let destination_pubkey = self.context.transfer_pubkeys.destination.try_into()?;
let auditor_pubkey = self.context.transfer_pubkeys.auditor.try_into()?;
let ciphertext_lo = self.context.ciphertext_lo.try_into()?; let ciphertext_lo = self.context.ciphertext_lo.try_into()?;
let ciphertext_hi = self.context.ciphertext_hi.try_into()?; let ciphertext_hi = self.context.ciphertext_hi.try_into()?;
let transfer_pubkeys = self.context.transfer_pubkeys.try_into()?;
let new_spendable_ciphertext = self.context.new_source_ciphertext.try_into()?; let new_spendable_ciphertext = self.context.new_source_ciphertext.try_into()?;
self.proof.verify( self.proof.verify(
&source_pubkey,
&destination_pubkey,
&auditor_pubkey,
&ciphertext_lo, &ciphertext_lo,
&ciphertext_hi, &ciphertext_hi,
&transfer_pubkeys,
&new_spendable_ciphertext, &new_spendable_ciphertext,
&mut transcript, &mut transcript,
) )
@ -353,9 +366,11 @@ impl TransferProof {
pub fn verify( pub fn verify(
&self, &self,
source_pubkey: &ElGamalPubkey,
destination_pubkey: &ElGamalPubkey,
auditor_pubkey: &ElGamalPubkey,
ciphertext_lo: &TransferAmountCiphertext, ciphertext_lo: &TransferAmountCiphertext,
ciphertext_hi: &TransferAmountCiphertext, ciphertext_hi: &TransferAmountCiphertext,
transfer_pubkeys: &TransferPubkeys,
ciphertext_new_spendable: &ElGamalCiphertext, ciphertext_new_spendable: &ElGamalCiphertext,
transcript: &mut Transcript, transcript: &mut Transcript,
) -> Result<(), ProofError> { ) -> Result<(), ProofError> {
@ -369,7 +384,7 @@ impl TransferProof {
// verify equality proof // verify equality proof
equality_proof.verify( equality_proof.verify(
&transfer_pubkeys.source_pubkey, source_pubkey,
ciphertext_new_spendable, ciphertext_new_spendable,
&commitment, &commitment,
transcript, transcript,
@ -377,10 +392,7 @@ impl TransferProof {
// verify validity proof // verify validity proof
aggregated_validity_proof.verify( aggregated_validity_proof.verify(
( (destination_pubkey, auditor_pubkey),
&transfer_pubkeys.destination_pubkey,
&transfer_pubkeys.auditor_pubkey,
),
( (
ciphertext_lo.get_commitment(), ciphertext_lo.get_commitment(),
ciphertext_hi.get_commitment(), ciphertext_hi.get_commitment(),
@ -436,46 +448,6 @@ impl TransferProof {
} }
} }
/// The ElGamal public keys needed for a transfer
#[derive(Clone)]
#[repr(C)]
#[cfg(not(target_os = "solana"))]
pub struct TransferPubkeys {
pub source_pubkey: ElGamalPubkey,
pub destination_pubkey: ElGamalPubkey,
pub auditor_pubkey: ElGamalPubkey,
}
#[cfg(not(target_os = "solana"))]
impl TransferPubkeys {
// TODO: use constructor instead
pub fn to_bytes(&self) -> [u8; 96] {
let mut bytes = [0u8; 96];
bytes[..32].copy_from_slice(&self.source_pubkey.to_bytes());
bytes[32..64].copy_from_slice(&self.destination_pubkey.to_bytes());
bytes[64..96].copy_from_slice(&self.auditor_pubkey.to_bytes());
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, ProofError> {
let bytes = array_ref![bytes, 0, 96];
let (source_pubkey, destination_pubkey, auditor_pubkey) = array_refs![bytes, 32, 32, 32];
let source_pubkey =
ElGamalPubkey::from_bytes(source_pubkey).ok_or(ProofError::PubkeyDeserialization)?;
let destination_pubkey = ElGamalPubkey::from_bytes(destination_pubkey)
.ok_or(ProofError::PubkeyDeserialization)?;
let auditor_pubkey =
ElGamalPubkey::from_bytes(auditor_pubkey).ok_or(ProofError::PubkeyDeserialization)?;
Ok(Self {
source_pubkey,
destination_pubkey,
auditor_pubkey,
})
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use {super::*, crate::encryption::elgamal::ElGamalKeypair}; use {super::*, crate::encryption::elgamal::ElGamalKeypair};

View File

@ -50,11 +50,7 @@ impl From<PodRistrettoPoint> for pod::DecryptHandle {
mod target_arch { mod target_arch {
use { use {
super::pod, super::pod,
crate::{ crate::{curve25519::scalar::PodScalar, errors::ProofError},
curve25519::scalar::PodScalar,
errors::ProofError,
instruction::transfer::{TransferPubkeys, TransferWithFeePubkeys},
},
curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar}, curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar},
std::convert::TryFrom, std::convert::TryFrom,
}; };
@ -84,54 +80,6 @@ mod target_arch {
Self(pod.0) Self(pod.0)
} }
} }
impl From<TransferPubkeys> for pod::TransferPubkeys {
fn from(keys: TransferPubkeys) -> Self {
Self {
source_pubkey: keys.source_pubkey.into(),
destination_pubkey: keys.destination_pubkey.into(),
auditor_pubkey: keys.auditor_pubkey.into(),
}
}
}
impl TryFrom<pod::TransferPubkeys> for TransferPubkeys {
type Error = ProofError;
fn try_from(pod: pod::TransferPubkeys) -> Result<Self, Self::Error> {
Ok(Self {
source_pubkey: pod.source_pubkey.try_into()?,
destination_pubkey: pod.destination_pubkey.try_into()?,
auditor_pubkey: pod.auditor_pubkey.try_into()?,
})
}
}
impl From<TransferWithFeePubkeys> for pod::TransferWithFeePubkeys {
fn from(keys: TransferWithFeePubkeys) -> Self {
Self {
source_pubkey: keys.source_pubkey.into(),
destination_pubkey: keys.destination_pubkey.into(),
auditor_pubkey: keys.auditor_pubkey.into(),
withdraw_withheld_authority_pubkey: keys.withdraw_withheld_authority_pubkey.into(),
}
}
}
impl TryFrom<pod::TransferWithFeePubkeys> for TransferWithFeePubkeys {
type Error = ProofError;
fn try_from(pod: pod::TransferWithFeePubkeys) -> Result<Self, Self::Error> {
Ok(Self {
source_pubkey: pod.source_pubkey.try_into()?,
destination_pubkey: pod.destination_pubkey.try_into()?,
auditor_pubkey: pod.auditor_pubkey.try_into()?,
withdraw_withheld_authority_pubkey: pod
.withdraw_withheld_authority_pubkey
.try_into()?,
})
}
}
} }
#[cfg(target_os = "solana")] #[cfg(target_os = "solana")]

View File

@ -1,27 +1,10 @@
use crate::zk_token_elgamal::pod::{ use crate::zk_token_elgamal::pod::{
ElGamalPubkey, GroupedElGamalCiphertext2Handles, GroupedElGamalCiphertext3Handles, Pod, PodU16, GroupedElGamalCiphertext2Handles, GroupedElGamalCiphertext3Handles, Pod, PodU16, PodU64,
PodU64, Zeroable, Zeroable,
}; };
#[cfg(not(target_os = "solana"))] #[cfg(not(target_os = "solana"))]
use crate::{errors::ProofError, instruction::transfer as decoded}; use crate::{errors::ProofError, instruction::transfer as decoded};
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
pub struct TransferPubkeys {
pub source_pubkey: ElGamalPubkey,
pub destination_pubkey: ElGamalPubkey,
pub auditor_pubkey: ElGamalPubkey,
}
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
pub struct TransferWithFeePubkeys {
pub source_pubkey: ElGamalPubkey,
pub destination_pubkey: ElGamalPubkey,
pub auditor_pubkey: ElGamalPubkey,
pub withdraw_withheld_authority_pubkey: ElGamalPubkey,
}
#[derive(Clone, Copy, Pod, Zeroable)] #[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)] #[repr(C)]
pub struct TransferAmountCiphertext(pub GroupedElGamalCiphertext3Handles); pub struct TransferAmountCiphertext(pub GroupedElGamalCiphertext3Handles);

View File

@ -16,10 +16,7 @@ pub use {
bytemuck::{Pod, Zeroable}, bytemuck::{Pod, Zeroable},
elgamal::{DecryptHandle, ElGamalCiphertext, ElGamalPubkey}, elgamal::{DecryptHandle, ElGamalCiphertext, ElGamalPubkey},
grouped_elgamal::{GroupedElGamalCiphertext2Handles, GroupedElGamalCiphertext3Handles}, grouped_elgamal::{GroupedElGamalCiphertext2Handles, GroupedElGamalCiphertext3Handles},
instruction::{ instruction::{FeeEncryption, FeeParameters, TransferAmountCiphertext},
FeeEncryption, FeeParameters, TransferAmountCiphertext, TransferPubkeys,
TransferWithFeePubkeys,
},
pedersen::PedersenCommitment, pedersen::PedersenCommitment,
range_proof::{RangeProofU128, RangeProofU256, RangeProofU64}, range_proof::{RangeProofU128, RangeProofU256, RangeProofU64},
sigma_proofs::{ sigma_proofs::{