zebra_chain/sapling/
commitment.rs1use std::io;
4
5use hex::{FromHex, FromHexError, ToHex};
6
7use crate::serialization::{serde_helpers, SerializationError, ZcashDeserialize, ZcashSerialize};
8
9#[cfg(test)]
10mod test_vectors;
11
12#[derive(Copy, Clone, Debug, PartialEq, Eq)]
17pub struct CommitmentRandomness(jubjub::Fr);
18
19#[derive(Clone, Debug, Deserialize, Serialize)]
23pub struct ValueCommitment(
24 #[serde(with = "serde_helpers::ValueCommitment")] pub sapling_crypto::value::ValueCommitment,
25);
26
27impl PartialEq for ValueCommitment {
28 fn eq(&self, other: &Self) -> bool {
29 self.0.as_inner() == other.0.as_inner()
30 }
31}
32impl Eq for ValueCommitment {}
33
34impl ValueCommitment {
35 pub fn bytes_in_display_order(&self) -> [u8; 32] {
40 let mut reversed_bytes = self.0.to_bytes();
41 reversed_bytes.reverse();
42 reversed_bytes
43 }
44}
45
46impl ToHex for &ValueCommitment {
47 fn encode_hex<T: FromIterator<char>>(&self) -> T {
48 self.bytes_in_display_order().encode_hex()
49 }
50
51 fn encode_hex_upper<T: FromIterator<char>>(&self) -> T {
52 self.bytes_in_display_order().encode_hex_upper()
53 }
54}
55
56impl FromHex for ValueCommitment {
57 type Error = FromHexError;
58
59 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
60 let mut bytes = <[u8; 32]>::from_hex(hex)?;
62 bytes.reverse();
64
65 Self::zcash_deserialize(io::Cursor::new(&bytes))
66 .map_err(|_| FromHexError::InvalidStringLength)
67 }
68}
69
70#[cfg(any(test, feature = "proptest-impl"))]
71impl From<jubjub::ExtendedPoint> for ValueCommitment {
72 fn from(extended_point: jubjub::ExtendedPoint) -> Self {
78 let bytes = jubjub::AffinePoint::from(extended_point).to_bytes();
79
80 let value_commitment =
81 sapling_crypto::value::ValueCommitment::from_bytes_not_small_order(&bytes)
82 .into_option()
83 .expect("invalid ValueCommitment bytes");
84
85 ValueCommitment(value_commitment)
86 }
87}
88
89impl ZcashDeserialize for sapling_crypto::value::ValueCommitment {
90 fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
91 let mut buf = [0u8; 32];
92 reader.read_exact(&mut buf)?;
93
94 let value_commitment: Option<sapling_crypto::value::ValueCommitment> =
95 sapling_crypto::value::ValueCommitment::from_bytes_not_small_order(&buf).into_option();
96
97 value_commitment.ok_or(SerializationError::Parse("invalid ValueCommitment bytes"))
98 }
99}
100
101impl ZcashDeserialize for ValueCommitment {
102 fn zcash_deserialize<R: io::Read>(reader: R) -> Result<Self, SerializationError> {
103 let value_commitment = sapling_crypto::value::ValueCommitment::zcash_deserialize(reader)?;
104 Ok(Self(value_commitment))
105 }
106}
107
108impl ZcashSerialize for ValueCommitment {
109 fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
110 writer.write_all(&self.0.to_bytes())?;
111 Ok(())
112 }
113}
114
115impl ZcashDeserialize for sapling_crypto::note::ExtractedNoteCommitment {
116 fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
117 let mut buf = [0u8; 32];
118 reader.read_exact(&mut buf)?;
119
120 let extracted_note_commitment: Option<sapling_crypto::note::ExtractedNoteCommitment> =
121 sapling_crypto::note::ExtractedNoteCommitment::from_bytes(&buf).into_option();
122
123 extracted_note_commitment.ok_or(SerializationError::Parse(
124 "invalid ExtractedNoteCommitment bytes",
125 ))
126 }
127}