[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:
parent
748223c928
commit
d654715adf
|
@ -20,7 +20,6 @@ use {
|
|||
},
|
||||
transcript::TranscriptProtocol,
|
||||
},
|
||||
arrayref::{array_ref, array_refs},
|
||||
bytemuck::bytes_of,
|
||||
curve25519_dalek::scalar::Scalar,
|
||||
merlin::Transcript,
|
||||
|
@ -87,7 +86,7 @@ pub struct TransferWithFeeProofContext {
|
|||
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
|
||||
pub transfer_with_fee_pubkeys: TransferWithFeePubkeys, // 128 bytes
|
||||
|
||||
/// The final spendable ciphertext after the transfer,
|
||||
pub new_source_ciphertext: pod::ElGamalCiphertext, // 64 bytes
|
||||
|
@ -102,6 +101,16 @@ pub struct TransferWithFeeProofContext {
|
|||
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"))]
|
||||
impl TransferWithFeeData {
|
||||
pub fn new(
|
||||
|
@ -177,11 +186,11 @@ impl TransferWithFeeData {
|
|||
);
|
||||
|
||||
// generate transcript and append all public inputs
|
||||
let pod_transfer_with_fee_pubkeys = pod::TransferWithFeePubkeys {
|
||||
source_pubkey: source_keypair.public.into(),
|
||||
destination_pubkey: (*destination_pubkey).into(),
|
||||
auditor_pubkey: (*auditor_pubkey).into(),
|
||||
withdraw_withheld_authority_pubkey: (*withdraw_withheld_authority_pubkey).into(),
|
||||
let pod_transfer_with_fee_pubkeys = TransferWithFeePubkeys {
|
||||
source: source_keypair.public.into(),
|
||||
destination: (*destination_pubkey).into(),
|
||||
auditor: (*auditor_pubkey).into(),
|
||||
withdraw_withheld_authority: (*withdraw_withheld_authority_pubkey).into(),
|
||||
};
|
||||
let pod_ciphertext_lo: pod::TransferAmountCiphertext = ciphertext_lo.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> {
|
||||
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_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 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();
|
||||
|
||||
self.proof.verify(
|
||||
&source_pubkey,
|
||||
&destination_pubkey,
|
||||
&auditor_pubkey,
|
||||
&withdraw_withheld_authority_pubkey,
|
||||
&ciphertext_lo,
|
||||
&ciphertext_hi,
|
||||
&pubkeys_transfer_with_fee,
|
||||
&new_source_ciphertext,
|
||||
&fee_ciphertext_lo,
|
||||
&fee_ciphertext_hi,
|
||||
|
@ -548,11 +572,15 @@ impl TransferWithFeeProof {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn verify(
|
||||
&self,
|
||||
source_pubkey: &ElGamalPubkey,
|
||||
destination_pubkey: &ElGamalPubkey,
|
||||
auditor_pubkey: &ElGamalPubkey,
|
||||
withdraw_withheld_authority_pubkey: &ElGamalPubkey,
|
||||
ciphertext_lo: &TransferAmountCiphertext,
|
||||
ciphertext_hi: &TransferAmountCiphertext,
|
||||
transfer_with_fee_pubkeys: &TransferWithFeePubkeys,
|
||||
new_spendable_ciphertext: &ElGamalCiphertext,
|
||||
// fee parameters
|
||||
fee_ciphertext_lo: &FeeEncryption,
|
||||
|
@ -575,7 +603,7 @@ impl TransferWithFeeProof {
|
|||
|
||||
// verify equality proof
|
||||
equality_proof.verify(
|
||||
&transfer_with_fee_pubkeys.source_pubkey,
|
||||
source_pubkey,
|
||||
new_spendable_ciphertext,
|
||||
&new_source_commitment,
|
||||
transcript,
|
||||
|
@ -583,10 +611,7 @@ impl TransferWithFeeProof {
|
|||
|
||||
// verify that the transfer amount is encrypted correctly
|
||||
ciphertext_amount_validity_proof.verify(
|
||||
(
|
||||
&transfer_with_fee_pubkeys.destination_pubkey,
|
||||
&transfer_with_fee_pubkeys.auditor_pubkey,
|
||||
),
|
||||
(destination_pubkey, auditor_pubkey),
|
||||
(
|
||||
ciphertext_lo.get_commitment(),
|
||||
ciphertext_hi.get_commitment(),
|
||||
|
@ -636,10 +661,7 @@ impl TransferWithFeeProof {
|
|||
|
||||
// verify ciphertext validity proof for fee ciphertexts
|
||||
fee_ciphertext_validity_proof.verify(
|
||||
(
|
||||
&transfer_with_fee_pubkeys.destination_pubkey,
|
||||
&transfer_with_fee_pubkeys.withdraw_withheld_authority_pubkey,
|
||||
),
|
||||
(destination_pubkey, withdraw_withheld_authority_pubkey),
|
||||
(
|
||||
fee_ciphertext_lo.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"))]
|
||||
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)?;
|
||||
|
|
|
@ -16,7 +16,6 @@ use {
|
|||
},
|
||||
transcript::TranscriptProtocol,
|
||||
},
|
||||
arrayref::{array_ref, array_refs},
|
||||
bytemuck::bytes_of,
|
||||
merlin::Transcript,
|
||||
std::convert::TryInto,
|
||||
|
@ -69,12 +68,21 @@ pub struct TransferProofContext {
|
|||
pub ciphertext_hi: pod::TransferAmountCiphertext, // 128 bytes
|
||||
|
||||
/// 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
|
||||
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"))]
|
||||
impl TransferData {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -124,10 +132,10 @@ impl TransferData {
|
|||
);
|
||||
|
||||
// generate transcript and append all public inputs
|
||||
let pod_transfer_pubkeys = pod::TransferPubkeys {
|
||||
source_pubkey: source_keypair.public.into(),
|
||||
destination_pubkey: (*destination_pubkey).into(),
|
||||
auditor_pubkey: (*auditor_pubkey).into(),
|
||||
let pod_transfer_pubkeys = TransferPubkeys {
|
||||
source: source_keypair.public.into(),
|
||||
destination: (*destination_pubkey).into(),
|
||||
auditor: (*auditor_pubkey).into(),
|
||||
};
|
||||
let pod_ciphertext_lo: pod::TransferAmountCiphertext = ciphertext_lo.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
|
||||
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_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()?;
|
||||
|
||||
self.proof.verify(
|
||||
&source_pubkey,
|
||||
&destination_pubkey,
|
||||
&auditor_pubkey,
|
||||
&ciphertext_lo,
|
||||
&ciphertext_hi,
|
||||
&transfer_pubkeys,
|
||||
&new_spendable_ciphertext,
|
||||
&mut transcript,
|
||||
)
|
||||
|
@ -353,9 +366,11 @@ impl TransferProof {
|
|||
|
||||
pub fn verify(
|
||||
&self,
|
||||
source_pubkey: &ElGamalPubkey,
|
||||
destination_pubkey: &ElGamalPubkey,
|
||||
auditor_pubkey: &ElGamalPubkey,
|
||||
ciphertext_lo: &TransferAmountCiphertext,
|
||||
ciphertext_hi: &TransferAmountCiphertext,
|
||||
transfer_pubkeys: &TransferPubkeys,
|
||||
ciphertext_new_spendable: &ElGamalCiphertext,
|
||||
transcript: &mut Transcript,
|
||||
) -> Result<(), ProofError> {
|
||||
|
@ -369,7 +384,7 @@ impl TransferProof {
|
|||
|
||||
// verify equality proof
|
||||
equality_proof.verify(
|
||||
&transfer_pubkeys.source_pubkey,
|
||||
source_pubkey,
|
||||
ciphertext_new_spendable,
|
||||
&commitment,
|
||||
transcript,
|
||||
|
@ -377,10 +392,7 @@ impl TransferProof {
|
|||
|
||||
// verify validity proof
|
||||
aggregated_validity_proof.verify(
|
||||
(
|
||||
&transfer_pubkeys.destination_pubkey,
|
||||
&transfer_pubkeys.auditor_pubkey,
|
||||
),
|
||||
(destination_pubkey, auditor_pubkey),
|
||||
(
|
||||
ciphertext_lo.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)]
|
||||
mod test {
|
||||
use {super::*, crate::encryption::elgamal::ElGamalKeypair};
|
||||
|
|
|
@ -50,11 +50,7 @@ impl From<PodRistrettoPoint> for pod::DecryptHandle {
|
|||
mod target_arch {
|
||||
use {
|
||||
super::pod,
|
||||
crate::{
|
||||
curve25519::scalar::PodScalar,
|
||||
errors::ProofError,
|
||||
instruction::transfer::{TransferPubkeys, TransferWithFeePubkeys},
|
||||
},
|
||||
crate::{curve25519::scalar::PodScalar, errors::ProofError},
|
||||
curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar},
|
||||
std::convert::TryFrom,
|
||||
};
|
||||
|
@ -84,54 +80,6 @@ mod target_arch {
|
|||
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")]
|
||||
|
|
|
@ -1,27 +1,10 @@
|
|||
use crate::zk_token_elgamal::pod::{
|
||||
ElGamalPubkey, GroupedElGamalCiphertext2Handles, GroupedElGamalCiphertext3Handles, Pod, PodU16,
|
||||
PodU64, Zeroable,
|
||||
GroupedElGamalCiphertext2Handles, GroupedElGamalCiphertext3Handles, Pod, PodU16, PodU64,
|
||||
Zeroable,
|
||||
};
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
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)]
|
||||
#[repr(C)]
|
||||
pub struct TransferAmountCiphertext(pub GroupedElGamalCiphertext3Handles);
|
||||
|
|
|
@ -16,10 +16,7 @@ pub use {
|
|||
bytemuck::{Pod, Zeroable},
|
||||
elgamal::{DecryptHandle, ElGamalCiphertext, ElGamalPubkey},
|
||||
grouped_elgamal::{GroupedElGamalCiphertext2Handles, GroupedElGamalCiphertext3Handles},
|
||||
instruction::{
|
||||
FeeEncryption, FeeParameters, TransferAmountCiphertext, TransferPubkeys,
|
||||
TransferWithFeePubkeys,
|
||||
},
|
||||
instruction::{FeeEncryption, FeeParameters, TransferAmountCiphertext},
|
||||
pedersen::PedersenCommitment,
|
||||
range_proof::{RangeProofU128, RangeProofU256, RangeProofU64},
|
||||
sigma_proofs::{
|
||||
|
|
Loading…
Reference in New Issue