phoenix_core/keys/
view.rs1use crate::{keys::hash, SecretKey, StealthAddress};
8
9use dusk_bytes::{DeserializableSlice, Error, Serializable};
10use dusk_jubjub::{
11 JubJubAffine, JubJubExtended, JubJubScalar, GENERATOR_EXTENDED,
12};
13use subtle::{Choice, ConstantTimeEq};
14
15#[cfg(feature = "rkyv-impl")]
16use rkyv::{Archive, Deserialize, Serialize};
17
18#[derive(Clone, Copy, Debug, Eq)]
23#[cfg_attr(
24 feature = "rkyv-impl",
25 derive(Archive, Serialize, Deserialize),
26 archive_attr(derive(bytecheck::CheckBytes))
27)]
28pub struct ViewKey {
29 a: JubJubScalar,
30 B: JubJubExtended,
31}
32
33impl ConstantTimeEq for ViewKey {
34 fn ct_eq(&self, other: &Self) -> Choice {
35 self.a.ct_eq(&other.a) & self.B.ct_eq(&other.B)
36 }
37}
38
39impl PartialEq for ViewKey {
40 fn eq(&self, other: &Self) -> bool {
41 self.ct_eq(other).into()
42 }
43}
44
45impl ViewKey {
46 pub fn new(a: JubJubScalar, B: JubJubExtended) -> Self {
49 Self { a, B }
50 }
51
52 pub fn a(&self) -> &JubJubScalar {
54 &self.a
55 }
56
57 pub fn B(&self) -> &JubJubExtended {
59 &self.B
60 }
61
62 pub fn owns(&self, stealth_address: &StealthAddress) -> bool {
64 let aR = stealth_address.R() * self.a();
65 let hash_aR = hash(&aR);
66 let hash_aR_G = GENERATOR_EXTENDED * hash_aR;
67 let note_pk = hash_aR_G + self.B();
68
69 stealth_address.note_pk().as_ref() == ¬e_pk
70 }
71}
72
73impl From<&SecretKey> for ViewKey {
74 fn from(sk: &SecretKey) -> Self {
75 let B = GENERATOR_EXTENDED * sk.b();
76
77 ViewKey::new(*sk.a(), B)
78 }
79}
80
81impl Serializable<64> for ViewKey {
82 type Error = Error;
83
84 fn to_bytes(&self) -> [u8; 64] {
85 let mut bytes = [0u8; 64];
86 bytes[..32].copy_from_slice(&self.a.to_bytes());
87 bytes[32..].copy_from_slice(&JubJubAffine::from(&self.B).to_bytes());
88 bytes
89 }
90
91 fn from_bytes(buf: &[u8; 64]) -> Result<Self, Self::Error> {
92 let a = JubJubScalar::from_slice(&buf[..32])?;
93 let B = JubJubExtended::from(JubJubAffine::from_slice(&buf[32..])?);
94
95 Ok(Self { a, B })
96 }
97}