diff --git a/zk-token-sdk/src/zk_token_elgamal/pod.rs b/zk-token-sdk/src/zk_token_elgamal/pod.rs deleted file mode 100644 index f76681a9633f7a..00000000000000 --- a/zk-token-sdk/src/zk_token_elgamal/pod.rs +++ /dev/null @@ -1,276 +0,0 @@ -pub use bytemuck::{Pod, Zeroable}; -use { - crate::zk_token_proof_instruction::ProofType, - base64::{prelude::BASE64_STANDARD, Engine}, - num_traits::{FromPrimitive, ToPrimitive}, - solana_program::instruction::InstructionError, - std::fmt, -}; - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Pod, Zeroable)] -#[repr(transparent)] -pub struct PodU16([u8; 2]); -impl From for PodU16 { - fn from(n: u16) -> Self { - Self(n.to_le_bytes()) - } -} -impl From for u16 { - fn from(pod: PodU16) -> Self { - Self::from_le_bytes(pod.0) - } -} - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Pod, Zeroable)] -#[repr(transparent)] -pub struct PodU64([u8; 8]); -impl From for PodU64 { - fn from(n: u64) -> Self { - Self(n.to_le_bytes()) - } -} -impl From for u64 { - fn from(pod: PodU64) -> Self { - Self::from_le_bytes(pod.0) - } -} - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Pod, Zeroable)] -#[repr(transparent)] -pub struct PodProofType(u8); -impl From for PodProofType { - fn from(proof_type: ProofType) -> Self { - Self(ToPrimitive::to_u8(&proof_type).unwrap()) - } -} -impl TryFrom for ProofType { - type Error = InstructionError; - - fn try_from(pod: PodProofType) -> Result { - FromPrimitive::from_u8(pod.0).ok_or(Self::Error::InvalidAccountData) - } -} - -#[derive(Clone, Copy, Pod, Zeroable, PartialEq, Eq)] -#[repr(transparent)] -pub struct CompressedRistretto(pub [u8; 32]); - -#[derive(Clone, Copy, Pod, Zeroable, PartialEq, Eq)] -#[repr(transparent)] -pub struct ElGamalCiphertext(pub [u8; 64]); - -impl fmt::Debug for ElGamalCiphertext { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -impl fmt::Display for ElGamalCiphertext { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", BASE64_STANDARD.encode(self.0)) - } -} - -impl Default for ElGamalCiphertext { - fn default() -> Self { - Self::zeroed() - } -} - -#[derive(Clone, Copy, Default, Pod, Zeroable, PartialEq, Eq)] -#[repr(transparent)] -pub struct ElGamalPubkey(pub [u8; 32]); - -impl fmt::Debug for ElGamalPubkey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -impl fmt::Display for ElGamalPubkey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", BASE64_STANDARD.encode(self.0)) - } -} - -#[derive(Clone, Copy, Default, Pod, Zeroable, PartialEq, Eq)] -#[repr(transparent)] -pub struct PedersenCommitment(pub [u8; 32]); - -impl fmt::Debug for PedersenCommitment { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -#[derive(Clone, Copy, Default, Pod, Zeroable, PartialEq, Eq)] -#[repr(transparent)] -pub struct DecryptHandle(pub [u8; 32]); - -impl fmt::Debug for DecryptHandle { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -/// Serialization of `CiphertextCommitmentEqualityProof` -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct CiphertextCommitmentEqualityProof(pub [u8; 192]); - -// `CiphertextCommitmentEqualityProof` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for CiphertextCommitmentEqualityProof {} -unsafe impl Pod for CiphertextCommitmentEqualityProof {} - -/// Serialization of `CtxtCtxtEqualityProof` -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct CiphertextCiphertextEqualityProof(pub [u8; 224]); - -// `CtxtCtxtEqualityProof` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for CiphertextCiphertextEqualityProof {} -unsafe impl Pod for CiphertextCiphertextEqualityProof {} - -/// Serialization of validity proofs -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct ValidityProof(pub [u8; 160]); - -// `ValidityProof` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for ValidityProof {} -unsafe impl Pod for ValidityProof {} - -/// Serialization of aggregated validity proofs -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct AggregatedValidityProof(pub [u8; 160]); - -// `AggregatedValidityProof` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for AggregatedValidityProof {} -unsafe impl Pod for AggregatedValidityProof {} - -/// Serialization of zero balance proofs -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct ZeroBalanceProof(pub [u8; 96]); - -// `ZeroBalanceProof` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for ZeroBalanceProof {} -unsafe impl Pod for ZeroBalanceProof {} - -/// Serialization of fee sigma proof -#[derive(Clone, Copy, Pod, Zeroable)] -#[repr(transparent)] -pub struct FeeSigmaProof(pub [u8; 256]); - -/// Serialization of public-key sigma proof -#[derive(Clone, Copy, Pod, Zeroable)] -#[repr(transparent)] -pub struct PubkeyValidityProof(pub [u8; 64]); - -/// Serialization of range proofs for 64-bit numbers (for `Withdraw` instruction) -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct RangeProof64(pub [u8; 672]); - -// `PodRangeProof64` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for RangeProof64 {} -unsafe impl Pod for RangeProof64 {} - -/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction) -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct RangeProof128(pub [u8; 736]); - -// `PodRangeProof128` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for RangeProof128 {} -unsafe impl Pod for RangeProof128 {} - -/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction) -#[derive(Clone, Copy)] -#[repr(transparent)] -pub struct RangeProof256(pub [u8; 800]); - -// `PodRangeProof256` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for RangeProof256 {} -unsafe impl Pod for RangeProof256 {} - -/// Serialization for AeCiphertext -#[derive(Clone, Copy, PartialEq, Eq)] -#[repr(transparent)] -pub struct AeCiphertext(pub [u8; 36]); - -// `AeCiphertext` is a Pod and Zeroable. -// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays -unsafe impl Zeroable for AeCiphertext {} -unsafe impl Pod for AeCiphertext {} - -impl fmt::Debug for AeCiphertext { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", self.0) - } -} - -impl fmt::Display for AeCiphertext { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", BASE64_STANDARD.encode(self.0)) - } -} - -impl Default for AeCiphertext { - fn default() -> Self { - Self::zeroed() - } -} - -// TODO: refactor this code into the instruction module -#[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 TransferAmountEncryption { - pub commitment: PedersenCommitment, - pub source_handle: DecryptHandle, - pub destination_handle: DecryptHandle, - pub auditor_handle: DecryptHandle, -} - -#[derive(Clone, Copy, Pod, Zeroable)] -#[repr(C)] -pub struct FeeEncryption { - pub commitment: PedersenCommitment, - pub destination_handle: DecryptHandle, - pub withdraw_withheld_authority_handle: DecryptHandle, -} - -#[derive(Clone, Copy, Pod, Zeroable)] -#[repr(C)] -pub struct FeeParameters { - /// Fee rate expressed as basis points of the transfer amount, i.e. increments of 0.01% - pub fee_rate_basis_points: PodU16, - /// Maximum fee assessed on transfers, expressed as an amount of tokens - pub maximum_fee: PodU64, -} diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/auth_encryption.rs b/zk-token-sdk/src/zk_token_elgamal/pod/auth_encryption.rs new file mode 100644 index 00000000000000..33bd1629099034 --- /dev/null +++ b/zk-token-sdk/src/zk_token_elgamal/pod/auth_encryption.rs @@ -0,0 +1,33 @@ +use { + crate::zk_token_elgamal::pod::{Pod, Zeroable}, + base64::{prelude::BASE64_STANDARD, Engine}, + std::fmt, +}; + +/// Serialization for AeCiphertext +#[derive(Clone, Copy, PartialEq, Eq)] +#[repr(transparent)] +pub struct AeCiphertext(pub [u8; 36]); + +// `AeCiphertext` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for AeCiphertext {} +unsafe impl Pod for AeCiphertext {} + +impl fmt::Debug for AeCiphertext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +impl fmt::Display for AeCiphertext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", BASE64_STANDARD.encode(self.0)) + } +} + +impl Default for AeCiphertext { + fn default() -> Self { + Self::zeroed() + } +} diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/elgamal.rs b/zk-token-sdk/src/zk_token_elgamal/pod/elgamal.rs new file mode 100644 index 00000000000000..438318852333ce --- /dev/null +++ b/zk-token-sdk/src/zk_token_elgamal/pod/elgamal.rs @@ -0,0 +1,43 @@ +use { + crate::zk_token_elgamal::pod::{Pod, Zeroable}, + base64::{prelude::BASE64_STANDARD, Engine}, + std::fmt, +}; + +#[derive(Clone, Copy, Pod, Zeroable, PartialEq, Eq)] +#[repr(transparent)] +pub struct ElGamalCiphertext(pub [u8; 64]); + +impl fmt::Debug for ElGamalCiphertext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +impl fmt::Display for ElGamalCiphertext { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", BASE64_STANDARD.encode(self.0)) + } +} + +impl Default for ElGamalCiphertext { + fn default() -> Self { + Self::zeroed() + } +} + +#[derive(Clone, Copy, Default, Pod, Zeroable, PartialEq, Eq)] +#[repr(transparent)] +pub struct ElGamalPubkey(pub [u8; 32]); + +impl fmt::Debug for ElGamalPubkey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +impl fmt::Display for ElGamalPubkey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", BASE64_STANDARD.encode(self.0)) + } +} diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/instruction.rs b/zk-token-sdk/src/zk_token_elgamal/pod/instruction.rs new file mode 100644 index 00000000000000..72939b18c9417d --- /dev/null +++ b/zk-token-sdk/src/zk_token_elgamal/pod/instruction.rs @@ -0,0 +1,46 @@ +use crate::zk_token_elgamal::pod::{ + DecryptHandle, ElGamalPubkey, PedersenCommitment, Pod, PodU16, PodU64, Zeroable, +}; + +#[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 TransferAmountEncryption { + pub commitment: PedersenCommitment, + pub source_handle: DecryptHandle, + pub destination_handle: DecryptHandle, + pub auditor_handle: DecryptHandle, +} + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct FeeEncryption { + pub commitment: PedersenCommitment, + pub destination_handle: DecryptHandle, + pub withdraw_withheld_authority_handle: DecryptHandle, +} + +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(C)] +pub struct FeeParameters { + /// Fee rate expressed as basis points of the transfer amount, i.e. increments of 0.01% + pub fee_rate_basis_points: PodU16, + /// Maximum fee assessed on transfers, expressed as an amount of tokens + pub maximum_fee: PodU64, +} diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/mod.rs b/zk-token-sdk/src/zk_token_elgamal/pod/mod.rs new file mode 100644 index 00000000000000..f70fc7fefda41c --- /dev/null +++ b/zk-token-sdk/src/zk_token_elgamal/pod/mod.rs @@ -0,0 +1,76 @@ +mod auth_encryption; +mod elgamal; +mod instruction; +mod pedersen; +mod range_proof; +mod sigma_proofs; + +use { + crate::zk_token_proof_instruction::ProofType, + num_traits::{FromPrimitive, ToPrimitive}, + solana_program::instruction::InstructionError, +}; +pub use { + auth_encryption::AeCiphertext, + bytemuck::{Pod, Zeroable}, + elgamal::{ElGamalCiphertext, ElGamalPubkey}, + instruction::{ + FeeEncryption, FeeParameters, TransferAmountEncryption, TransferPubkeys, + TransferWithFeePubkeys, + }, + pedersen::{DecryptHandle, PedersenCommitment}, + range_proof::{RangeProof128, RangeProof256, RangeProof64}, + sigma_proofs::{ + AggregatedValidityProof, CiphertextCiphertextEqualityProof, + CiphertextCommitmentEqualityProof, FeeSigmaProof, PubkeyValidityProof, ValidityProof, + ZeroBalanceProof, + }, +}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Pod, Zeroable)] +#[repr(transparent)] +pub struct PodU16([u8; 2]); +impl From for PodU16 { + fn from(n: u16) -> Self { + Self(n.to_le_bytes()) + } +} +impl From for u16 { + fn from(pod: PodU16) -> Self { + Self::from_le_bytes(pod.0) + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Pod, Zeroable)] +#[repr(transparent)] +pub struct PodU64([u8; 8]); +impl From for PodU64 { + fn from(n: u64) -> Self { + Self(n.to_le_bytes()) + } +} +impl From for u64 { + fn from(pod: PodU64) -> Self { + Self::from_le_bytes(pod.0) + } +} + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Pod, Zeroable)] +#[repr(transparent)] +pub struct PodProofType(u8); +impl From for PodProofType { + fn from(proof_type: ProofType) -> Self { + Self(ToPrimitive::to_u8(&proof_type).unwrap()) + } +} +impl TryFrom for ProofType { + type Error = InstructionError; + + fn try_from(pod: PodProofType) -> Result { + FromPrimitive::from_u8(pod.0).ok_or(Self::Error::InvalidAccountData) + } +} + +#[derive(Clone, Copy, Pod, Zeroable, PartialEq, Eq)] +#[repr(transparent)] +pub struct CompressedRistretto(pub [u8; 32]); diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/pedersen.rs b/zk-token-sdk/src/zk_token_elgamal/pod/pedersen.rs new file mode 100644 index 00000000000000..7a0229f9f5b3c3 --- /dev/null +++ b/zk-token-sdk/src/zk_token_elgamal/pod/pedersen.rs @@ -0,0 +1,24 @@ +use { + crate::zk_token_elgamal::pod::{Pod, Zeroable}, + std::fmt, +}; + +#[derive(Clone, Copy, Default, Pod, Zeroable, PartialEq, Eq)] +#[repr(transparent)] +pub struct PedersenCommitment(pub [u8; 32]); + +impl fmt::Debug for PedersenCommitment { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + +#[derive(Clone, Copy, Default, Pod, Zeroable, PartialEq, Eq)] +#[repr(transparent)] +pub struct DecryptHandle(pub [u8; 32]); + +impl fmt::Debug for DecryptHandle { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/range_proof.rs b/zk-token-sdk/src/zk_token_elgamal/pod/range_proof.rs new file mode 100644 index 00000000000000..7a1699dde1e0eb --- /dev/null +++ b/zk-token-sdk/src/zk_token_elgamal/pod/range_proof.rs @@ -0,0 +1,31 @@ +use crate::zk_token_elgamal::pod::{Pod, Zeroable}; + +/// Serialization of range proofs for 64-bit numbers (for `Withdraw` instruction) +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct RangeProof64(pub [u8; 672]); + +// `PodRangeProof64` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for RangeProof64 {} +unsafe impl Pod for RangeProof64 {} + +/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction) +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct RangeProof128(pub [u8; 736]); + +// `PodRangeProof128` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for RangeProof128 {} +unsafe impl Pod for RangeProof128 {} + +/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction) +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct RangeProof256(pub [u8; 800]); + +// `PodRangeProof256` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for RangeProof256 {} +unsafe impl Pod for RangeProof256 {} diff --git a/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs b/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs new file mode 100644 index 00000000000000..226b7f90ca5ea2 --- /dev/null +++ b/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs @@ -0,0 +1,61 @@ +use crate::zk_token_elgamal::pod::{Pod, Zeroable}; + +/// Serialization of `CiphertextCommitmentEqualityProof` +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct CiphertextCommitmentEqualityProof(pub [u8; 192]); + +// `CiphertextCommitmentEqualityProof` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for CiphertextCommitmentEqualityProof {} +unsafe impl Pod for CiphertextCommitmentEqualityProof {} + +/// Serialization of `CiphertextCiphertextEqualityProof` +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct CiphertextCiphertextEqualityProof(pub [u8; 224]); + +// `CiphertextCiphertextEqualityProof` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for CiphertextCiphertextEqualityProof {} +unsafe impl Pod for CiphertextCiphertextEqualityProof {} + +/// Serialization of validity proofs +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct ValidityProof(pub [u8; 160]); + +// `ValidityProof` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for ValidityProof {} +unsafe impl Pod for ValidityProof {} + +/// Serialization of aggregated validity proofs +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct AggregatedValidityProof(pub [u8; 160]); + +// `AggregatedValidityProof` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for AggregatedValidityProof {} +unsafe impl Pod for AggregatedValidityProof {} + +/// Serialization of zero balance proofs +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct ZeroBalanceProof(pub [u8; 96]); + +// `ZeroBalanceProof` is a Pod and Zeroable. +// Add the marker traits manually because `bytemuck` only adds them for some `u8` arrays +unsafe impl Zeroable for ZeroBalanceProof {} +unsafe impl Pod for ZeroBalanceProof {} + +/// Serialization of fee sigma proof +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(transparent)] +pub struct FeeSigmaProof(pub [u8; 256]); + +/// Serialization of public-key sigma proof +#[derive(Clone, Copy, Pod, Zeroable)] +#[repr(transparent)] +pub struct PubkeyValidityProof(pub [u8; 64]);