zebra_chain/primitives/proofs/
groth16.rs

1//! Groth16 proofs for Zebra.
2
3use std::{fmt, io};
4
5use serde::{Deserialize, Serialize};
6use serde_big_array::BigArray;
7
8use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize};
9
10/// An encoding of a Groth16 proof, as used in Zcash.
11#[derive(Serialize, Deserialize)]
12pub struct Groth16Proof(#[serde(with = "BigArray")] pub [u8; 192]);
13
14impl fmt::Debug for Groth16Proof {
15    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16        f.debug_tuple("Groth16Proof")
17            .field(&hex::encode(&self.0[..]))
18            .finish()
19    }
20}
21
22// These impls all only exist because of array length restrictions.
23
24impl Copy for Groth16Proof {}
25
26impl Clone for Groth16Proof {
27    fn clone(&self) -> Self {
28        *self
29    }
30}
31
32impl Eq for Groth16Proof {}
33
34impl From<[u8; 192]> for Groth16Proof {
35    fn from(bytes: [u8; 192]) -> Groth16Proof {
36        Self(bytes)
37    }
38}
39
40impl From<Groth16Proof> for [u8; 192] {
41    fn from(rt: Groth16Proof) -> [u8; 192] {
42        rt.0
43    }
44}
45
46impl PartialEq for Groth16Proof {
47    fn eq(&self, other: &Self) -> bool {
48        self.0[..] == other.0[..]
49    }
50}
51
52impl ZcashSerialize for Groth16Proof {
53    fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
54        writer.write_all(&self.0[..])?;
55        Ok(())
56    }
57}
58
59impl ZcashDeserialize for Groth16Proof {
60    fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
61        let mut bytes = [0; 192];
62        reader.read_exact(&mut bytes[..])?;
63        Ok(Self(bytes))
64    }
65}
66
67#[cfg(any(test, feature = "proptest-impl"))]
68use proptest::{collection::vec, prelude::*};
69
70#[cfg(any(test, feature = "proptest-impl"))]
71impl Arbitrary for Groth16Proof {
72    type Parameters = ();
73
74    fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
75        (vec(any::<u8>(), 192))
76            .prop_map(|v| {
77                let mut bytes = [0; 192];
78                bytes.copy_from_slice(v.as_slice());
79                Self(bytes)
80            })
81            .boxed()
82    }
83
84    type Strategy = BoxedStrategy<Self>;
85}