[zk-token-sdk] Refactor `zk-token-elgamal` conversion code for authenticated encryption, range proof, and sigma proof types (#31855)

* refactor convert logic for `AeCiphertext`

* refactor convert logic for `RangeProof`

* refactor convert logic for sigma proof types

* Apply suggestions from code review

Co-authored-by: Tyera <teulberg@gmail.com>

---------

Co-authored-by: Tyera <teulberg@gmail.com>
This commit is contained in:
samkim-crypto 2023-05-31 08:12:38 +09:00 committed by GitHub
parent 66558fb5c4
commit e4fe9335e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 283 additions and 257 deletions

View File

@ -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<AeCiphertext> for pod::AeCiphertext {
fn from(ct: AeCiphertext) -> Self {
Self(ct.to_bytes())
}
}
impl TryFrom<pod::AeCiphertext> for AeCiphertext {
type Error = ProofError;
fn try_from(ct: pod::AeCiphertext) -> Result<Self, Self::Error> {
Self::from_bytes(&ct.0).ok_or(ProofError::CiphertextDeserialization)
}
}
impl From<CiphertextCommitmentEqualityProof> for pod::CiphertextCommitmentEqualityProof {
fn from(proof: CiphertextCommitmentEqualityProof) -> Self {
Self(proof.to_bytes())
}
}
impl TryFrom<pod::CiphertextCommitmentEqualityProof> for CiphertextCommitmentEqualityProof {
type Error = EqualityProofError;
fn try_from(pod: pod::CiphertextCommitmentEqualityProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl From<CiphertextCiphertextEqualityProof> for pod::CiphertextCiphertextEqualityProof {
fn from(proof: CiphertextCiphertextEqualityProof) -> Self {
Self(proof.to_bytes())
}
}
impl TryFrom<pod::CiphertextCiphertextEqualityProof> for CiphertextCiphertextEqualityProof {
type Error = EqualityProofError;
fn try_from(pod: pod::CiphertextCiphertextEqualityProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl From<ValidityProof> for pod::ValidityProof {
fn from(proof: ValidityProof) -> Self {
Self(proof.to_bytes())
}
}
impl TryFrom<pod::ValidityProof> for ValidityProof {
type Error = ValidityProofError;
fn try_from(pod: pod::ValidityProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl From<AggregatedValidityProof> for pod::AggregatedValidityProof {
fn from(proof: AggregatedValidityProof) -> Self {
Self(proof.to_bytes())
}
}
impl TryFrom<pod::AggregatedValidityProof> for AggregatedValidityProof {
type Error = ValidityProofError;
fn try_from(pod: pod::AggregatedValidityProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl From<ZeroBalanceProof> for pod::ZeroBalanceProof {
fn from(proof: ZeroBalanceProof) -> Self {
Self(proof.to_bytes())
}
}
impl TryFrom<pod::ZeroBalanceProof> for ZeroBalanceProof {
type Error = ZeroBalanceProofError;
fn try_from(pod: pod::ZeroBalanceProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl From<FeeSigmaProof> for pod::FeeSigmaProof {
fn from(proof: FeeSigmaProof) -> Self {
Self(proof.to_bytes())
}
}
impl TryFrom<pod::FeeSigmaProof> for FeeSigmaProof {
type Error = FeeSigmaProofError;
fn try_from(pod: pod::FeeSigmaProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl From<PubkeyValidityProof> for pod::PubkeyValidityProof {
fn from(proof: PubkeyValidityProof) -> Self {
Self(proof.to_bytes())
}
}
impl TryFrom<pod::PubkeyValidityProof> for PubkeyValidityProof {
type Error = PubkeyValidityProofError;
fn try_from(pod: pod::PubkeyValidityProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl TryFrom<RangeProof> for pod::RangeProof64 {
type Error = RangeProofError;
fn try_from(proof: RangeProof) -> Result<Self, Self::Error> {
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<pod::RangeProof64> for RangeProof {
type Error = RangeProofError;
fn try_from(pod: pod::RangeProof64) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
#[cfg(not(target_os = "solana"))]
impl TryFrom<RangeProof> for pod::RangeProof128 {
type Error = RangeProofError;
fn try_from(proof: RangeProof) -> Result<Self, Self::Error> {
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<pod::RangeProof128> for RangeProof {
type Error = RangeProofError;
fn try_from(pod: pod::RangeProof128) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
#[cfg(not(target_os = "solana"))]
impl TryFrom<RangeProof> for pod::RangeProof256 {
type Error = RangeProofError;
fn try_from(proof: RangeProof) -> Result<Self, Self::Error> {
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<pod::RangeProof256> for RangeProof {
type Error = RangeProofError;
fn try_from(pod: pod::RangeProof256) -> Result<Self, Self::Error> {
Self::from_bytes(&pod.0)
}
}
impl From<TransferPubkeys> for pod::TransferPubkeys {
fn from(keys: TransferPubkeys) -> Self {
Self {

View File

@ -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<decoded::AeCiphertext> for AeCiphertext {
fn from(decoded_ciphertext: decoded::AeCiphertext) -> Self {
Self(decoded_ciphertext.to_bytes())
}
}
#[cfg(not(target_os = "solana"))]
impl TryFrom<AeCiphertext> for decoded::AeCiphertext {
type Error = ProofError;
fn try_from(pod_ciphertext: AeCiphertext) -> Result<Self, Self::Error> {
Self::from_bytes(&pod_ciphertext.0).ok_or(ProofError::CiphertextDeserialization)
}
}

View File

@ -1,31 +1,128 @@
use crate::zk_token_elgamal::pod::{Pod, Zeroable};
//! Plain Old Data types for range proofs.
/// Serialization of range proofs for 64-bit numbers (for `Withdraw` instruction)
use crate::zk_token_elgamal::pod::{Pod, Zeroable};
#[cfg(not(target_os = "solana"))]
use crate::{
errors::ProofVerificationError,
range_proof::{self as decoded, errors::RangeProofError},
};
/// 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<decoded::RangeProof> for RangeProof64 {
type Error = RangeProofError;
/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction)
fn try_from(decoded_proof: decoded::RangeProof) -> Result<Self, Self::Error> {
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<RangeProof64> for decoded::RangeProof {
type Error = RangeProofError;
fn try_from(pod_proof: RangeProof64) -> Result<Self, Self::Error> {
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<decoded::RangeProof> for RangeProof128 {
type Error = RangeProofError;
/// Serialization of range proofs for 128-bit numbers (for `TransferRangeProof` instruction)
fn try_from(decoded_proof: decoded::RangeProof) -> Result<Self, Self::Error> {
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<RangeProof128> for decoded::RangeProof {
type Error = RangeProofError;
fn try_from(pod_proof: RangeProof128) -> Result<Self, Self::Error> {
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<decoded::RangeProof> for RangeProof256 {
type Error = RangeProofError;
fn try_from(decoded_proof: decoded::RangeProof) -> Result<Self, Self::Error> {
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<RangeProof256> for decoded::RangeProof {
type Error = RangeProofError;
fn try_from(pod_proof: RangeProof256) -> Result<Self, Self::Error> {
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 {}

View File

@ -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<DecodedCiphertextCommitmentEqualityProof> for CiphertextCommitmentEqualityProof {
fn from(decoded_proof: DecodedCiphertextCommitmentEqualityProof) -> Self {
Self(decoded_proof.to_bytes())
}
}
/// Serialization of `CiphertextCiphertextEqualityProof`
#[cfg(not(target_os = "solana"))]
impl TryFrom<CiphertextCommitmentEqualityProof> for DecodedCiphertextCommitmentEqualityProof {
type Error = EqualityProofError;
fn try_from(pod_proof: CiphertextCommitmentEqualityProof) -> Result<Self, Self::Error> {
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<DecodedCiphertextCiphertextEqualityProof> for CiphertextCiphertextEqualityProof {
fn from(decoded_proof: DecodedCiphertextCiphertextEqualityProof) -> Self {
Self(decoded_proof.to_bytes())
}
}
/// Serialization of validity proofs
#[cfg(not(target_os = "solana"))]
impl TryFrom<CiphertextCiphertextEqualityProof> for DecodedCiphertextCiphertextEqualityProof {
type Error = EqualityProofError;
fn try_from(pod_proof: CiphertextCiphertextEqualityProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod_proof.0)
}
}
/// 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<DecodedValidityProof> 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<ValidityProof> for DecodedValidityProof {
type Error = ValidityProofError;
fn try_from(pod_proof: ValidityProof) -> Result<Self, Self::Error> {
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<DecodedAggregatedValidityProof> for AggregatedValidityProof {
fn from(decoded_proof: DecodedAggregatedValidityProof) -> Self {
Self(decoded_proof.to_bytes())
}
}
/// Serialization of zero balance proofs
#[cfg(not(target_os = "solana"))]
impl TryFrom<AggregatedValidityProof> for DecodedAggregatedValidityProof {
type Error = ValidityProofError;
fn try_from(pod_proof: AggregatedValidityProof) -> Result<Self, Self::Error> {
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<DecodedZeroBalanceProof> for ZeroBalanceProof {
fn from(decoded_proof: DecodedZeroBalanceProof) -> Self {
Self(decoded_proof.to_bytes())
}
}
/// Serialization of fee sigma proof
#[cfg(not(target_os = "solana"))]
impl TryFrom<ZeroBalanceProof> for DecodedZeroBalanceProof {
type Error = ZeroBalanceProofError;
fn try_from(pod_proof: ZeroBalanceProof) -> Result<Self, Self::Error> {
Self::from_bytes(&pod_proof.0)
}
}
/// 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<DecodedFeeSigmaProof> for FeeSigmaProof {
fn from(decoded_proof: DecodedFeeSigmaProof) -> Self {
Self(decoded_proof.to_bytes())
}
}
#[cfg(not(target_os = "solana"))]
impl TryFrom<FeeSigmaProof> for DecodedFeeSigmaProof {
type Error = FeeSigmaProofError;
fn try_from(pod_proof: FeeSigmaProof) -> Result<Self, Self::Error> {
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<DecodedPubkeyValidityProof> for PubkeyValidityProof {
fn from(decoded_proof: DecodedPubkeyValidityProof) -> Self {
Self(decoded_proof.to_bytes())
}
}
#[cfg(not(target_os = "solana"))]
impl TryFrom<PubkeyValidityProof> for DecodedPubkeyValidityProof {
type Error = PubkeyValidityProofError;
fn try_from(pod_proof: PubkeyValidityProof) -> Result<Self, Self::Error> {
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 {}