1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use crate::{JubJubAffine, JubJubExtended, PublicKey};
#[cfg(feature = "canon")]
use canonical_derive::Canon;
use dusk_bytes::{DeserializableSlice, Error, HexDebug, Serializable};
use subtle::{Choice, ConstantTimeEq};
#[derive(HexDebug, Clone, Copy)]
#[cfg_attr(feature = "canon", derive(Canon))]
pub struct StealthAddress {
pub(crate) R: JubJubExtended,
pub(crate) pk_r: PublicKey,
}
pub trait Ownable {
fn stealth_address(&self) -> &StealthAddress;
}
impl StealthAddress {
pub fn R(&self) -> &JubJubExtended {
&self.R
}
pub fn pk_r(&self) -> &PublicKey {
&self.pk_r
}
pub fn address(&self) -> &JubJubExtended {
&self.pk_r.as_ref()
}
}
impl ConstantTimeEq for StealthAddress {
fn ct_eq(&self, other: &Self) -> Choice {
self.pk_r.as_ref().ct_eq(&other.pk_r.as_ref()) & self.R.ct_eq(&other.R)
}
}
impl PartialEq for StealthAddress {
fn eq(&self, other: &Self) -> bool {
self.ct_eq(&other).into()
}
}
impl Ownable for StealthAddress {
fn stealth_address(&self) -> &StealthAddress {
&self
}
}
impl Serializable<64> for StealthAddress {
type Error = Error;
fn to_bytes(&self) -> [u8; Self::SIZE] {
let mut bytes = [0u8; Self::SIZE];
bytes[..32].copy_from_slice(&JubJubAffine::from(self.R).to_bytes());
bytes[32..].copy_from_slice(
&JubJubAffine::from(self.pk_r.as_ref()).to_bytes(),
);
bytes
}
fn from_bytes(bytes: &[u8; Self::SIZE]) -> Result<Self, Error> {
let R = JubJubExtended::from(JubJubAffine::from_slice(&bytes[..32])?);
let pk_r =
JubJubExtended::from(JubJubAffine::from_slice(&bytes[32..])?);
let pk_r = PublicKey(pk_r);
Ok(StealthAddress { R, pk_r })
}
}