diff --git a/zk-token-sdk/src/zk_token_elgamal/convert.rs b/zk-token-sdk/src/zk_token_elgamal/convert.rs index c51c400cd0d5a8..d171a873d03e79 100644 --- a/zk-token-sdk/src/zk_token_elgamal/convert.rs +++ b/zk-token-sdk/src/zk_token_elgamal/convert.rs @@ -52,22 +52,11 @@ mod target_arch { super::pod, crate::{ curve25519::scalar::PodScalar, - encryption::auth_encryption::AeCiphertext, - errors::{ProofError, ProofVerificationError}, + errors::ProofError, instruction::{ transfer::{TransferAmountEncryption, TransferPubkeys}, transfer_with_fee::{FeeEncryption, FeeParameters, TransferWithFeePubkeys}, }, - range_proof::{errors::RangeProofError, RangeProof}, - sigma_proofs::{ - ciphertext_ciphertext_equality_proof::CiphertextCiphertextEqualityProof, - ciphertext_commitment_equality_proof::CiphertextCommitmentEqualityProof, - errors::*, - fee_proof::FeeSigmaProof, - pubkey_proof::PubkeyValidityProof, - validity_proof::{AggregatedValidityProof, ValidityProof}, - zero_balance_proof::ZeroBalanceProof, - }, }, curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar}, std::convert::TryFrom, @@ -99,207 +88,6 @@ mod target_arch { } } - impl From for pod::AeCiphertext { - fn from(ct: AeCiphertext) -> Self { - Self(ct.to_bytes()) - } - } - - impl TryFrom for AeCiphertext { - type Error = ProofError; - - fn try_from(ct: pod::AeCiphertext) -> Result { - Self::from_bytes(&ct.0).ok_or(ProofError::CiphertextDeserialization) - } - } - - impl From for pod::CiphertextCommitmentEqualityProof { - fn from(proof: CiphertextCommitmentEqualityProof) -> Self { - Self(proof.to_bytes()) - } - } - - impl TryFrom for CiphertextCommitmentEqualityProof { - type Error = EqualityProofError; - - fn try_from(pod: pod::CiphertextCommitmentEqualityProof) -> Result { - Self::from_bytes(&pod.0) - } - } - - impl From for pod::CiphertextCiphertextEqualityProof { - fn from(proof: CiphertextCiphertextEqualityProof) -> Self { - Self(proof.to_bytes()) - } - } - - impl TryFrom for CiphertextCiphertextEqualityProof { - type Error = EqualityProofError; - - fn try_from(pod: pod::CiphertextCiphertextEqualityProof) -> Result { - Self::from_bytes(&pod.0) - } - } - - impl From for pod::ValidityProof { - fn from(proof: ValidityProof) -> Self { - Self(proof.to_bytes()) - } - } - - impl TryFrom for ValidityProof { - type Error = ValidityProofError; - - fn try_from(pod: pod::ValidityProof) -> Result { - Self::from_bytes(&pod.0) - } - } - - impl From for pod::AggregatedValidityProof { - fn from(proof: AggregatedValidityProof) -> Self { - Self(proof.to_bytes()) - } - } - - impl TryFrom for AggregatedValidityProof { - type Error = ValidityProofError; - - fn try_from(pod: pod::AggregatedValidityProof) -> Result { - Self::from_bytes(&pod.0) - } - } - - impl From for pod::ZeroBalanceProof { - fn from(proof: ZeroBalanceProof) -> Self { - Self(proof.to_bytes()) - } - } - - impl TryFrom for ZeroBalanceProof { - type Error = ZeroBalanceProofError; - - fn try_from(pod: pod::ZeroBalanceProof) -> Result { - Self::from_bytes(&pod.0) - } - } - - impl From for pod::FeeSigmaProof { - fn from(proof: FeeSigmaProof) -> Self { - Self(proof.to_bytes()) - } - } - - impl TryFrom for FeeSigmaProof { - type Error = FeeSigmaProofError; - - fn try_from(pod: pod::FeeSigmaProof) -> Result { - Self::from_bytes(&pod.0) - } - } - - impl From for pod::PubkeyValidityProof { - fn from(proof: PubkeyValidityProof) -> Self { - Self(proof.to_bytes()) - } - } - - impl TryFrom for PubkeyValidityProof { - type Error = PubkeyValidityProofError; - - fn try_from(pod: pod::PubkeyValidityProof) -> Result { - Self::from_bytes(&pod.0) - } - } - - impl TryFrom for pod::RangeProof64 { - type Error = RangeProofError; - - fn try_from(proof: RangeProof) -> Result { - if proof.ipp_proof.serialized_size() != 448 { - return Err(ProofVerificationError::Deserialization.into()); - } - - let mut buf = [0_u8; 672]; - buf[..32].copy_from_slice(proof.A.as_bytes()); - buf[32..64].copy_from_slice(proof.S.as_bytes()); - buf[64..96].copy_from_slice(proof.T_1.as_bytes()); - buf[96..128].copy_from_slice(proof.T_2.as_bytes()); - buf[128..160].copy_from_slice(proof.t_x.as_bytes()); - buf[160..192].copy_from_slice(proof.t_x_blinding.as_bytes()); - buf[192..224].copy_from_slice(proof.e_blinding.as_bytes()); - buf[224..672].copy_from_slice(&proof.ipp_proof.to_bytes()); - Ok(pod::RangeProof64(buf)) - } - } - - impl TryFrom for RangeProof { - type Error = RangeProofError; - - fn try_from(pod: pod::RangeProof64) -> Result { - Self::from_bytes(&pod.0) - } - } - - #[cfg(not(target_os = "solana"))] - impl TryFrom for pod::RangeProof128 { - type Error = RangeProofError; - - fn try_from(proof: RangeProof) -> Result { - if proof.ipp_proof.serialized_size() != 512 { - return Err(ProofVerificationError::Deserialization.into()); - } - - let mut buf = [0_u8; 736]; - buf[..32].copy_from_slice(proof.A.as_bytes()); - buf[32..64].copy_from_slice(proof.S.as_bytes()); - buf[64..96].copy_from_slice(proof.T_1.as_bytes()); - buf[96..128].copy_from_slice(proof.T_2.as_bytes()); - buf[128..160].copy_from_slice(proof.t_x.as_bytes()); - buf[160..192].copy_from_slice(proof.t_x_blinding.as_bytes()); - buf[192..224].copy_from_slice(proof.e_blinding.as_bytes()); - buf[224..736].copy_from_slice(&proof.ipp_proof.to_bytes()); - Ok(pod::RangeProof128(buf)) - } - } - - impl TryFrom for RangeProof { - type Error = RangeProofError; - - fn try_from(pod: pod::RangeProof128) -> Result { - Self::from_bytes(&pod.0) - } - } - - #[cfg(not(target_os = "solana"))] - impl TryFrom for pod::RangeProof256 { - type Error = RangeProofError; - - fn try_from(proof: RangeProof) -> Result { - if proof.ipp_proof.serialized_size() != 576 { - return Err(ProofVerificationError::Deserialization.into()); - } - - let mut buf = [0_u8; 800]; - buf[..32].copy_from_slice(proof.A.as_bytes()); - buf[32..64].copy_from_slice(proof.S.as_bytes()); - buf[64..96].copy_from_slice(proof.T_1.as_bytes()); - buf[96..128].copy_from_slice(proof.T_2.as_bytes()); - buf[128..160].copy_from_slice(proof.t_x.as_bytes()); - buf[160..192].copy_from_slice(proof.t_x_blinding.as_bytes()); - buf[192..224].copy_from_slice(proof.e_blinding.as_bytes()); - buf[224..800].copy_from_slice(&proof.ipp_proof.to_bytes()); - Ok(pod::RangeProof256(buf)) - } - } - - impl TryFrom for RangeProof { - type Error = RangeProofError; - - fn try_from(pod: pod::RangeProof256) -> Result { - Self::from_bytes(&pod.0) - } - } - impl From for pod::TransferPubkeys { fn from(keys: TransferPubkeys) -> Self { Self { 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 index 33bd1629099034..6666ffe648c5b6 100644 --- a/zk-token-sdk/src/zk_token_elgamal/pod/auth_encryption.rs +++ b/zk-token-sdk/src/zk_token_elgamal/pod/auth_encryption.rs @@ -1,16 +1,21 @@ +//! Plain Old Data types for the AES128-GCM-SIV authenticated encryption scheme. + +#[cfg(not(target_os = "solana"))] +use crate::{encryption::auth_encryption as decoded, errors::ProofError}; use { crate::zk_token_elgamal::pod::{Pod, Zeroable}, base64::{prelude::BASE64_STANDARD, Engine}, std::fmt, }; -/// Serialization for AeCiphertext +/// The `AeCiphertext` type as a `Pod`. #[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 +// `AeCiphertext` is a wrapper type for a byte array, which is both `Pod` and `Zeroable`. However, +// the marker traits `bytemuck::Pod` and `bytemuck::Zeroable` can only be derived for power-of-two +// length byte arrays. Directly implement these traits for `AeCiphertext`. unsafe impl Zeroable for AeCiphertext {} unsafe impl Pod for AeCiphertext {} @@ -31,3 +36,19 @@ impl Default for AeCiphertext { Self::zeroed() } } + +#[cfg(not(target_os = "solana"))] +impl From for AeCiphertext { + fn from(decoded_ciphertext: decoded::AeCiphertext) -> Self { + Self(decoded_ciphertext.to_bytes()) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for decoded::AeCiphertext { + type Error = ProofError; + + fn try_from(pod_ciphertext: AeCiphertext) -> Result { + Self::from_bytes(&pod_ciphertext.0).ok_or(ProofError::CiphertextDeserialization) + } +} 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 index 7a1699dde1e0eb..e20212c8412f3b 100644 --- a/zk-token-sdk/src/zk_token_elgamal/pod/range_proof.rs +++ b/zk-token-sdk/src/zk_token_elgamal/pod/range_proof.rs @@ -1,31 +1,128 @@ +//! Plain Old Data types for range proofs. + use crate::zk_token_elgamal::pod::{Pod, Zeroable}; +#[cfg(not(target_os = "solana"))] +use crate::{ + errors::ProofVerificationError, + range_proof::{self as decoded, errors::RangeProofError}, +}; -/// Serialization of range proofs for 64-bit numbers (for `Withdraw` instruction) +/// The `RangeProof` type as a `Pod` restricted to proofs on 64-bit numbers. #[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 {} +#[cfg(not(target_os = "solana"))] +impl TryFrom for RangeProof64 { + type Error = RangeProofError; + + fn try_from(decoded_proof: decoded::RangeProof) -> Result { + if decoded_proof.ipp_proof.serialized_size() != 448 { + return Err(ProofVerificationError::Deserialization.into()); + } + + let mut buf = [0_u8; 672]; + buf[..32].copy_from_slice(decoded_proof.A.as_bytes()); + buf[32..64].copy_from_slice(decoded_proof.S.as_bytes()); + buf[64..96].copy_from_slice(decoded_proof.T_1.as_bytes()); + buf[96..128].copy_from_slice(decoded_proof.T_2.as_bytes()); + buf[128..160].copy_from_slice(decoded_proof.t_x.as_bytes()); + buf[160..192].copy_from_slice(decoded_proof.t_x_blinding.as_bytes()); + buf[192..224].copy_from_slice(decoded_proof.e_blinding.as_bytes()); + buf[224..672].copy_from_slice(&decoded_proof.ipp_proof.to_bytes()); + Ok(RangeProof64(buf)) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for decoded::RangeProof { + type Error = RangeProofError; -/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction) + fn try_from(pod_proof: RangeProof64) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +/// The `RangeProof` type as a `Pod` restricted to proofs on 128-bit numbers. #[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 {} +#[cfg(not(target_os = "solana"))] +impl TryFrom for RangeProof128 { + type Error = RangeProofError; + + fn try_from(decoded_proof: decoded::RangeProof) -> Result { + if decoded_proof.ipp_proof.serialized_size() != 512 { + return Err(ProofVerificationError::Deserialization.into()); + } + + let mut buf = [0_u8; 736]; + buf[..32].copy_from_slice(decoded_proof.A.as_bytes()); + buf[32..64].copy_from_slice(decoded_proof.S.as_bytes()); + buf[64..96].copy_from_slice(decoded_proof.T_1.as_bytes()); + buf[96..128].copy_from_slice(decoded_proof.T_2.as_bytes()); + buf[128..160].copy_from_slice(decoded_proof.t_x.as_bytes()); + buf[160..192].copy_from_slice(decoded_proof.t_x_blinding.as_bytes()); + buf[192..224].copy_from_slice(decoded_proof.e_blinding.as_bytes()); + buf[224..736].copy_from_slice(&decoded_proof.ipp_proof.to_bytes()); + Ok(RangeProof128(buf)) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for decoded::RangeProof { + type Error = RangeProofError; -/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction) + fn try_from(pod_proof: RangeProof128) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +/// The `RangeProof` type as a `Pod` restricted to proofs on 256-bit numbers. #[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 +#[cfg(not(target_os = "solana"))] +impl TryFrom for RangeProof256 { + type Error = RangeProofError; + + fn try_from(decoded_proof: decoded::RangeProof) -> Result { + if decoded_proof.ipp_proof.serialized_size() != 576 { + return Err(ProofVerificationError::Deserialization.into()); + } + + let mut buf = [0_u8; 800]; + buf[..32].copy_from_slice(decoded_proof.A.as_bytes()); + buf[32..64].copy_from_slice(decoded_proof.S.as_bytes()); + buf[64..96].copy_from_slice(decoded_proof.T_1.as_bytes()); + buf[96..128].copy_from_slice(decoded_proof.T_2.as_bytes()); + buf[128..160].copy_from_slice(decoded_proof.t_x.as_bytes()); + buf[160..192].copy_from_slice(decoded_proof.t_x_blinding.as_bytes()); + buf[192..224].copy_from_slice(decoded_proof.e_blinding.as_bytes()); + buf[224..800].copy_from_slice(&decoded_proof.ipp_proof.to_bytes()); + Ok(RangeProof256(buf)) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for decoded::RangeProof { + type Error = RangeProofError; + + fn try_from(pod_proof: RangeProof256) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +// The range proof pod types are wrappers for byte arrays, which are both `Pod` and `Zeroable`. However, +// the marker traits `bytemuck::Pod` and `bytemuck::Zeroable` can only be derived for power-of-two +// length byte arrays. Directly implement these traits for the range proof pod types. +unsafe impl Zeroable for RangeProof64 {} +unsafe impl Pod for RangeProof64 {} + +unsafe impl Zeroable for RangeProof128 {} +unsafe impl Pod for RangeProof128 {} + 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 index 226b7f90ca5ea2..4cb96902dedff3 100644 --- a/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs +++ b/zk-token-sdk/src/zk_token_elgamal/pod/sigma_proofs.rs @@ -1,61 +1,181 @@ +//! Plain Old Data types for sigma proofs. + +#[cfg(not(target_os = "solana"))] +use crate::sigma_proofs::{ + ciphertext_ciphertext_equality_proof::CiphertextCiphertextEqualityProof as DecodedCiphertextCiphertextEqualityProof, + ciphertext_commitment_equality_proof::CiphertextCommitmentEqualityProof as DecodedCiphertextCommitmentEqualityProof, + errors::*, + fee_proof::FeeSigmaProof as DecodedFeeSigmaProof, + pubkey_proof::PubkeyValidityProof as DecodedPubkeyValidityProof, + validity_proof::{ + AggregatedValidityProof as DecodedAggregatedValidityProof, + ValidityProof as DecodedValidityProof, + }, + zero_balance_proof::ZeroBalanceProof as DecodedZeroBalanceProof, +}; use crate::zk_token_elgamal::pod::{Pod, Zeroable}; -/// Serialization of `CiphertextCommitmentEqualityProof` +/// The `CiphertextCommitmentEqualityProof` type as a `Pod`. #[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 {} +#[cfg(not(target_os = "solana"))] +impl From for CiphertextCommitmentEqualityProof { + fn from(decoded_proof: DecodedCiphertextCommitmentEqualityProof) -> Self { + Self(decoded_proof.to_bytes()) + } +} -/// Serialization of `CiphertextCiphertextEqualityProof` +#[cfg(not(target_os = "solana"))] +impl TryFrom for DecodedCiphertextCommitmentEqualityProof { + type Error = EqualityProofError; + + fn try_from(pod_proof: CiphertextCommitmentEqualityProof) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +/// The `CiphertextCiphertextEqualityProof` type as a `Pod`. #[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 {} +#[cfg(not(target_os = "solana"))] +impl From for CiphertextCiphertextEqualityProof { + fn from(decoded_proof: DecodedCiphertextCiphertextEqualityProof) -> Self { + Self(decoded_proof.to_bytes()) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for DecodedCiphertextCiphertextEqualityProof { + type Error = EqualityProofError; + + fn try_from(pod_proof: CiphertextCiphertextEqualityProof) -> Result { + Self::from_bytes(&pod_proof.0) + } +} -/// Serialization of validity proofs +/// The `ValidityProof` type as a `Pod`. #[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 {} +#[cfg(not(target_os = "solana"))] +impl From for ValidityProof { + fn from(decoded_proof: DecodedValidityProof) -> Self { + Self(decoded_proof.to_bytes()) + } +} -/// Serialization of aggregated validity proofs +#[cfg(not(target_os = "solana"))] +impl TryFrom for DecodedValidityProof { + type Error = ValidityProofError; + + fn try_from(pod_proof: ValidityProof) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +/// The `AggregatedValidityProof` type as a `Pod`. #[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 {} +#[cfg(not(target_os = "solana"))] +impl From for AggregatedValidityProof { + fn from(decoded_proof: DecodedAggregatedValidityProof) -> Self { + Self(decoded_proof.to_bytes()) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for DecodedAggregatedValidityProof { + type Error = ValidityProofError; -/// Serialization of zero balance proofs + fn try_from(pod_proof: AggregatedValidityProof) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +/// The `ZeroBalanceProof` type as a `Pod`. #[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 {} +#[cfg(not(target_os = "solana"))] +impl From for ZeroBalanceProof { + fn from(decoded_proof: DecodedZeroBalanceProof) -> Self { + Self(decoded_proof.to_bytes()) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for DecodedZeroBalanceProof { + type Error = ZeroBalanceProofError; + + fn try_from(pod_proof: ZeroBalanceProof) -> Result { + Self::from_bytes(&pod_proof.0) + } +} -/// Serialization of fee sigma proof +/// The `FeeSigmaProof` type as a `Pod`. #[derive(Clone, Copy, Pod, Zeroable)] #[repr(transparent)] pub struct FeeSigmaProof(pub [u8; 256]); -/// Serialization of public-key sigma proof +#[cfg(not(target_os = "solana"))] +impl From for FeeSigmaProof { + fn from(decoded_proof: DecodedFeeSigmaProof) -> Self { + Self(decoded_proof.to_bytes()) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for DecodedFeeSigmaProof { + type Error = FeeSigmaProofError; + + fn try_from(pod_proof: FeeSigmaProof) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +/// The `PubkeyValidityProof` type as a `Pod`. #[derive(Clone, Copy, Pod, Zeroable)] #[repr(transparent)] pub struct PubkeyValidityProof(pub [u8; 64]); + +#[cfg(not(target_os = "solana"))] +impl From for PubkeyValidityProof { + fn from(decoded_proof: DecodedPubkeyValidityProof) -> Self { + Self(decoded_proof.to_bytes()) + } +} + +#[cfg(not(target_os = "solana"))] +impl TryFrom for DecodedPubkeyValidityProof { + type Error = PubkeyValidityProofError; + + fn try_from(pod_proof: PubkeyValidityProof) -> Result { + Self::from_bytes(&pod_proof.0) + } +} + +// The sigma proof pod types are wrappers for byte arrays, which are both `Pod` and `Zeroable`. However, +// the marker traits `bytemuck::Pod` and `bytemuck::Zeroable` can only be derived for power-of-two +// length byte arrays. Directly implement these traits for the sigma proof pod types. +unsafe impl Zeroable for CiphertextCommitmentEqualityProof {} +unsafe impl Pod for CiphertextCommitmentEqualityProof {} + +unsafe impl Zeroable for CiphertextCiphertextEqualityProof {} +unsafe impl Pod for CiphertextCiphertextEqualityProof {} + +unsafe impl Zeroable for ValidityProof {} +unsafe impl Pod for ValidityProof {} + +unsafe impl Zeroable for AggregatedValidityProof {} +unsafe impl Pod for AggregatedValidityProof {} + +unsafe impl Zeroable for ZeroBalanceProof {} +unsafe impl Pod for ZeroBalanceProof {}