zebra_chain/orchard/
keys.rs1use std::{fmt, io};
8
9use group::{ff::PrimeField, prime::PrimeCurveAffine, Group, GroupEncoding};
10use halo2::{
11    arithmetic::{Coordinates, CurveAffine},
12    pasta::pallas,
13};
14use rand_core::{CryptoRng, RngCore};
15
16use crate::{
17    error::RandError,
18    serialization::{
19        serde_helpers, ReadZcashExt, SerializationError, ZcashDeserialize, ZcashSerialize,
20    },
21};
22
23use super::sinsemilla::*;
24
25fn diversify_hash(d: &[u8]) -> pallas::Point {
34    let p = pallas_group_hash(b"z.cash:Orchard-gd", d);
35
36    if <bool>::from(p.is_identity()) {
37        pallas_group_hash(b"z.cash:Orchard-gd", b"")
38    } else {
39        p
40    }
41}
42
43#[derive(Copy, Clone, Eq, PartialEq)]
47#[cfg_attr(
48    any(test, feature = "proptest-impl"),
49    derive(proptest_derive::Arbitrary)
50)]
51pub struct Diversifier(pub(crate) [u8; 11]);
52
53impl fmt::Debug for Diversifier {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        f.debug_tuple("Diversifier")
56            .field(&hex::encode(self.0))
57            .finish()
58    }
59}
60
61impl From<[u8; 11]> for Diversifier {
62    fn from(bytes: [u8; 11]) -> Self {
63        Self(bytes)
64    }
65}
66
67impl From<Diversifier> for [u8; 11] {
68    fn from(d: Diversifier) -> [u8; 11] {
69        d.0
70    }
71}
72
73impl From<Diversifier> for pallas::Point {
74    fn from(d: Diversifier) -> Self {
80        diversify_hash(&d.0)
81    }
82}
83
84impl PartialEq<[u8; 11]> for Diversifier {
85    fn eq(&self, other: &[u8; 11]) -> bool {
86        self.0 == *other
87    }
88}
89
90impl From<Diversifier> for pallas::Affine {
91    fn from(d: Diversifier) -> Self {
94        let projective_point = pallas::Point::from(d);
95        projective_point.into()
96    }
97}
98
99impl Diversifier {
100    pub fn new<T>(csprng: &mut T) -> Result<Self, RandError>
104    where
105        T: RngCore + CryptoRng,
106    {
107        let mut bytes = [0u8; 11];
108        csprng
109            .try_fill_bytes(&mut bytes)
110            .map_err(|_| RandError::FillBytes)?;
111
112        Ok(Self::from(bytes))
113    }
114}
115
116#[derive(Copy, Clone, PartialEq)]
129pub struct TransmissionKey(pub(crate) pallas::Affine);
130
131impl fmt::Debug for TransmissionKey {
132    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133        let mut d = f.debug_struct("TransmissionKey");
134
135        let option: Option<Coordinates<pallas::Affine>> = self.0.coordinates().into();
136
137        match option {
138            Some(coordinates) => d
139                .field("x", &hex::encode(coordinates.x().to_repr()))
140                .field("y", &hex::encode(coordinates.y().to_repr()))
141                .finish(),
142            None => d
143                .field("x", &hex::encode(pallas::Base::zero().to_repr()))
144                .field("y", &hex::encode(pallas::Base::zero().to_repr()))
145                .finish(),
146        }
147    }
148}
149
150impl Eq for TransmissionKey {}
151
152impl From<TransmissionKey> for [u8; 32] {
153    fn from(pk_d: TransmissionKey) -> [u8; 32] {
154        pk_d.0.to_bytes()
155    }
156}
157
158impl PartialEq<[u8; 32]> for TransmissionKey {
159    fn eq(&self, other: &[u8; 32]) -> bool {
160        &self.0.to_bytes() == other
161    }
162}
163
164#[derive(Copy, Clone, Deserialize, PartialEq, Eq, Serialize)]
169pub struct EphemeralPublicKey(#[serde(with = "serde_helpers::Affine")] pub(crate) pallas::Affine);
170
171impl fmt::Debug for EphemeralPublicKey {
172    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173        let mut d = f.debug_struct("EphemeralPublicKey");
174
175        let option: Option<Coordinates<pallas::Affine>> = self.0.coordinates().into();
176
177        match option {
178            Some(coordinates) => d
179                .field("x", &hex::encode(coordinates.x().to_repr()))
180                .field("y", &hex::encode(coordinates.y().to_repr()))
181                .finish(),
182            None => d
183                .field("x", &hex::encode(pallas::Base::zero().to_repr()))
184                .field("y", &hex::encode(pallas::Base::zero().to_repr()))
185                .finish(),
186        }
187    }
188}
189
190impl From<EphemeralPublicKey> for [u8; 32] {
191    fn from(epk: EphemeralPublicKey) -> [u8; 32] {
192        epk.0.to_bytes()
193    }
194}
195
196impl From<&EphemeralPublicKey> for [u8; 32] {
197    fn from(epk: &EphemeralPublicKey) -> [u8; 32] {
198        epk.0.to_bytes()
199    }
200}
201
202impl PartialEq<[u8; 32]> for EphemeralPublicKey {
203    fn eq(&self, other: &[u8; 32]) -> bool {
204        &self.0.to_bytes() == other
205    }
206}
207
208impl TryFrom<[u8; 32]> for EphemeralPublicKey {
209    type Error = &'static str;
210
211    fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
226        let possible_point = pallas::Affine::from_bytes(&bytes);
227
228        if possible_point.is_some().into() {
229            let point = possible_point.unwrap();
230            if point.to_curve().is_identity().into() {
231                Err("pallas::Affine value for Orchard EphemeralPublicKey is the identity")
232            } else {
233                Ok(Self(possible_point.unwrap()))
234            }
235        } else {
236            Err("Invalid pallas::Affine value for Orchard EphemeralPublicKey")
237        }
238    }
239}
240
241impl ZcashSerialize for EphemeralPublicKey {
242    fn zcash_serialize<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
243        writer.write_all(&<[u8; 32]>::from(self)[..])?;
244        Ok(())
245    }
246}
247
248impl ZcashDeserialize for EphemeralPublicKey {
249    fn zcash_deserialize<R: io::Read>(mut reader: R) -> Result<Self, SerializationError> {
250        Self::try_from(reader.read_32_bytes()?).map_err(SerializationError::Parse)
251    }
252}