Skip to main content

pijul_core/pristine/
merkle.rs

1use super::{BASE32, Base32};
2use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
3
4pub(crate) const BASE32_BYTES: usize = 53;
5
6#[doc(hidden)]
7#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8pub enum Merkle {
9    Ed25519(curve25519_dalek::edwards::EdwardsPoint),
10}
11
12impl Default for Merkle {
13    fn default() -> Self {
14        Merkle::zero()
15    }
16}
17
18#[doc(hidden)]
19#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
20#[repr(u8)]
21pub enum MerkleAlgorithm {
22    Ed25519 = 1,
23}
24
25impl std::fmt::Debug for Merkle {
26    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
27        write!(fmt, "{:?}", self.to_base32())
28    }
29}
30
31impl std::fmt::Debug for SerializedMerkle {
32    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
33        Merkle::from(self).fmt(fmt)
34    }
35}
36
37impl std::hash::Hash for Merkle {
38    fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
39        match self {
40            Merkle::Ed25519(x) => x.compress().as_bytes().hash(hasher),
41        }
42    }
43}
44
45impl From<&super::Hash> for curve25519_dalek::scalar::Scalar {
46    fn from(h: &super::Hash) -> Self {
47        match h {
48            super::Hash::Blake3(h) => curve25519_dalek::scalar::Scalar::from_bytes_mod_order(*h),
49            #[cfg(feature = "git2")]
50            super::Hash::GitSha2(h) => curve25519_dalek::scalar::Scalar::from_bytes_mod_order(*h),
51            #[cfg(feature = "git2")]
52            super::Hash::GitSha1(h) => {
53                let mut hh = [0; 32];
54                hh[..super::hash::GIT_SHA1_BYTES].clone_from_slice(h);
55                curve25519_dalek::scalar::Scalar::from_bytes_mod_order(hh)
56            }
57            _ => unreachable!(),
58        }
59    }
60}
61
62impl From<&super::SerializedHash> for curve25519_dalek::scalar::Scalar {
63    fn from(h: &super::SerializedHash) -> Self {
64        let h: super::Hash = h.into();
65        (&h).into()
66    }
67}
68
69impl From<&Merkle> for curve25519_dalek::scalar::Scalar {
70    fn from(h: &Merkle) -> Self {
71        match *h {
72            Merkle::Ed25519(h) => {
73                let h = h.compress();
74                curve25519_dalek::scalar::Scalar::from_bytes_mod_order(*h.as_bytes())
75            }
76        }
77    }
78}
79
80impl From<&super::SerializedMerkle> for curve25519_dalek::scalar::Scalar {
81    fn from(h: &super::SerializedMerkle) -> Self {
82        let h: Merkle = h.into();
83        (&h).into()
84    }
85}
86
87impl Merkle {
88    pub fn zero() -> Self {
89        Merkle::Ed25519(ED25519_BASEPOINT_POINT)
90    }
91    pub fn next<S: Into<curve25519_dalek::scalar::Scalar>>(&self, h: S) -> Self {
92        match self {
93            Merkle::Ed25519(h0) => {
94                let scalar = h.into();
95                Merkle::Ed25519(h0 * scalar)
96            }
97        }
98    }
99    pub fn to_bytes(&self) -> [u8; 32] {
100        match *self {
101            Merkle::Ed25519(ref e) => e.compress().to_bytes(),
102        }
103    }
104
105    pub fn from_prefix(s: &str) -> Option<Self> {
106        let mut b32 = [b'A'; BASE32_BYTES];
107        if s.len() > BASE32_BYTES {
108            return None;
109        }
110        b32[..s.len()].clone_from_slice(s.as_bytes());
111        let bytes = if let Ok(bytes) = BASE32.decode(&b32) {
112            bytes
113        } else {
114            return None;
115        };
116        curve25519_dalek::edwards::CompressedEdwardsY::from_slice(&bytes[..32])
117            .unwrap()
118            .decompress()
119            .map(Merkle::Ed25519)
120    }
121}
122
123impl super::Base32 for Merkle {
124    fn to_base32(&self) -> String {
125        match *self {
126            Merkle::Ed25519(ref s) => {
127                let mut hash = [0; 33];
128                hash[..32].clone_from_slice(s.compress().as_bytes());
129                hash[32] = MerkleAlgorithm::Ed25519 as u8;
130                BASE32.encode(&hash)
131            }
132        }
133    }
134
135    /// Parses a base-32 string into a `Merkle`.
136    fn from_base32(s: &[u8]) -> Option<Self> {
137        let bytes = if let Ok(b) = BASE32.decode(s) {
138            b
139        } else {
140            return None;
141        };
142        if bytes.len() == 33 && *bytes.last().unwrap() == MerkleAlgorithm::Ed25519 as u8 {
143            curve25519_dalek::edwards::CompressedEdwardsY::from_slice(&bytes[..32])
144                .unwrap()
145                .decompress()
146                .map(Merkle::Ed25519)
147        } else {
148            None
149        }
150    }
151}
152
153impl std::str::FromStr for Merkle {
154    type Err = crate::ParseError;
155    fn from_str(s: &str) -> Result<Self, Self::Err> {
156        if let Some(b) = Self::from_base32(s.as_bytes()) {
157            Ok(b)
158        } else {
159            Err(crate::ParseError { s: s.to_string() })
160        }
161    }
162}
163
164#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
165pub struct SerializedMerkle(pub [u8; 33]);
166
167impl PartialEq<Merkle> for SerializedMerkle {
168    fn eq(&self, m: &Merkle) -> bool {
169        match m {
170            Merkle::Ed25519(q) => {
171                (self.0)[0] == MerkleAlgorithm::Ed25519 as u8 && {
172                    let q = q.compress();
173                    q.as_bytes() == &(self.0)[1..]
174                }
175            }
176        }
177    }
178}
179
180impl PartialEq<SerializedMerkle> for Merkle {
181    fn eq(&self, m: &SerializedMerkle) -> bool {
182        m.eq(self)
183    }
184}
185
186impl<'a> From<&'a Merkle> for SerializedMerkle {
187    fn from(m: &'a Merkle) -> Self {
188        let mut mm = [0; 33];
189        match m {
190            Merkle::Ed25519(q) => {
191                mm[0] = MerkleAlgorithm::Ed25519 as u8;
192                let q = q.compress();
193                let q = q.as_bytes();
194                mm[1..].copy_from_slice(q);
195                SerializedMerkle(mm)
196            }
197        }
198    }
199}
200
201impl From<Merkle> for SerializedMerkle {
202    fn from(m: Merkle) -> Self {
203        let mut mm = [0; 33];
204        match m {
205            Merkle::Ed25519(q) => {
206                mm[0] = MerkleAlgorithm::Ed25519 as u8;
207                let q = q.compress();
208                let q = q.as_bytes();
209                mm[1..].copy_from_slice(q);
210                SerializedMerkle(mm)
211            }
212        }
213    }
214}
215
216impl<'a> From<&'a SerializedMerkle> for Merkle {
217    fn from(m: &'a SerializedMerkle) -> Self {
218        assert_eq!((m.0)[0], MerkleAlgorithm::Ed25519 as u8);
219        Merkle::Ed25519(
220            curve25519_dalek::edwards::CompressedEdwardsY::from_slice(&(m.0)[1..])
221                .unwrap()
222                .decompress()
223                .unwrap(),
224        )
225    }
226}
227
228impl From<SerializedMerkle> for Merkle {
229    fn from(m: SerializedMerkle) -> Self {
230        assert_eq!((m.0)[0], MerkleAlgorithm::Ed25519 as u8);
231        Merkle::Ed25519(
232            curve25519_dalek::edwards::CompressedEdwardsY::from_slice(&(m.0)[1..])
233                .unwrap()
234                .decompress()
235                .unwrap(),
236        )
237    }
238}