light_compressed_account/instruction_data/
compressed_proof.rs

1use light_zero_copy::{errors::ZeroCopyError, traits::ZeroCopyAt, ZeroCopyMut};
2use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, Unaligned};
3
4#[repr(C)]
5#[cfg_attr(
6    all(feature = "std", feature = "anchor"),
7    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
8)]
9#[cfg_attr(
10    not(feature = "anchor"),
11    derive(borsh::BorshDeserialize, borsh::BorshSerialize)
12)]
13#[derive(
14    Debug,
15    Clone,
16    Copy,
17    PartialEq,
18    Eq,
19    KnownLayout,
20    Immutable,
21    FromBytes,
22    IntoBytes,
23    Unaligned,
24    ZeroCopyMut,
25)]
26pub struct CompressedProof {
27    pub a: [u8; 32],
28    pub b: [u8; 64],
29    pub c: [u8; 32],
30}
31
32impl Default for CompressedProof {
33    fn default() -> Self {
34        Self {
35            a: [0; 32],
36            b: [0; 64],
37            c: [0; 32],
38        }
39    }
40}
41
42impl CompressedProof {
43    /// Convert the proof to a fixed-size byte array [u8; 128]
44    pub fn to_array(&self) -> [u8; 128] {
45        let mut result = [0u8; 128];
46        result[0..32].copy_from_slice(&self.a);
47        result[32..96].copy_from_slice(&self.b);
48        result[96..128].copy_from_slice(&self.c);
49        result
50    }
51}
52
53impl TryFrom<&[u8]> for CompressedProof {
54    type Error = crate::CompressedAccountError;
55
56    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
57        if bytes.len() < 128 {
58            return Err(crate::CompressedAccountError::InvalidProofSize(bytes.len()));
59        }
60        let mut a = [0u8; 32];
61        let mut b = [0u8; 64];
62        let mut c = [0u8; 32];
63        a.copy_from_slice(&bytes[0..32]);
64        b.copy_from_slice(&bytes[32..96]);
65        c.copy_from_slice(&bytes[96..128]);
66        Ok(Self { a, b, c })
67    }
68}
69
70impl<'a> ZeroCopyAt<'a> for CompressedProof {
71    type ZeroCopyAt = Ref<&'a [u8], Self>;
72    fn zero_copy_at(bytes: &'a [u8]) -> Result<(Self::ZeroCopyAt, &'a [u8]), ZeroCopyError> {
73        Ok(Ref::<&[u8], CompressedProof>::from_prefix(bytes)?)
74    }
75}
76
77#[cfg_attr(
78    all(feature = "std", feature = "anchor"),
79    derive(anchor_lang::AnchorDeserialize, anchor_lang::AnchorSerialize)
80)]
81#[cfg_attr(
82    not(feature = "anchor"),
83    derive(borsh::BorshDeserialize, borsh::BorshSerialize)
84)]
85#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
86pub struct ValidityProof(pub Option<CompressedProof>);
87
88impl ValidityProof {
89    pub fn new(proof: Option<CompressedProof>) -> Self {
90        Self(proof)
91    }
92
93    /// Convert the validity proof to a fixed-size byte array [u8; 128]
94    /// Returns None if the proof is None
95    pub fn to_array(&self) -> Option<[u8; 128]> {
96        self.0.as_ref().map(|proof| proof.to_array())
97    }
98}
99
100impl From<CompressedProof> for ValidityProof {
101    fn from(proof: CompressedProof) -> Self {
102        Self(Some(proof))
103    }
104}
105
106impl From<Option<CompressedProof>> for ValidityProof {
107    fn from(proof: Option<CompressedProof>) -> Self {
108        Self(proof)
109    }
110}
111impl From<&CompressedProof> for ValidityProof {
112    fn from(proof: &CompressedProof) -> Self {
113        Self(Some(*proof))
114    }
115}
116
117impl From<&Option<CompressedProof>> for ValidityProof {
118    fn from(proof: &Option<CompressedProof>) -> Self {
119        Self(*proof)
120    }
121}
122
123impl TryFrom<&[u8]> for ValidityProof {
124    type Error = crate::CompressedAccountError;
125
126    /// Convert bytes to ValidityProof.
127    /// Empty slice returns None, otherwise attempts to parse as CompressedProof and returns Some.
128    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
129        if bytes.is_empty() {
130            Ok(Self(None))
131        } else {
132            let proof = CompressedProof::try_from(bytes)?;
133            Ok(Self(Some(proof)))
134        }
135    }
136}
137
138#[allow(clippy::from_over_into)]
139impl Into<Option<CompressedProof>> for ValidityProof {
140    fn into(self) -> Option<CompressedProof> {
141        self.0
142    }
143}