1use alloc::vec;
2use alloc::vec::{IntoIter, Vec};
3use core::borrow::Borrow;
4use core::marker::PhantomData;
5
6use p3_util::log2_strict_usize;
7use serde::de::Error;
8use serde::{Deserialize, Deserializer, Serialize};
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(bound(serialize = "[W; DIGEST_ELEMS]: Serialize"))]
14#[serde(bound(deserialize = "[W; DIGEST_ELEMS]: Deserialize<'de>"))]
15pub struct Hash<F, W, const DIGEST_ELEMS: usize> {
16 value: [W; DIGEST_ELEMS],
17 _marker: PhantomData<F>,
18}
19
20#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
34#[serde(bound(serialize = "Digest: Serialize"))]
35pub struct MerkleCap<F, Digest> {
36 cap: Vec<Digest>,
37 _marker: PhantomData<F>,
38}
39
40#[derive(Deserialize)]
48#[serde(rename = "MerkleCap")]
49#[serde(bound(deserialize = "Digest: Deserialize<'de>"))]
50struct MerkleCapRepr<F, Digest> {
51 cap: Vec<Digest>,
53 _marker: PhantomData<F>,
55}
56
57impl<'de, F, Digest: Deserialize<'de>> Deserialize<'de> for MerkleCap<F, Digest> {
58 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
66 let MerkleCapRepr { cap, _marker } = MerkleCapRepr::<F, Digest>::deserialize(deserializer)?;
68
69 if !cap.len().is_power_of_two() {
75 return Err(D::Error::invalid_length(
76 cap.len(),
77 &"a power-of-two number of Merkle cap roots",
78 ));
79 }
80
81 Ok(Self { cap, _marker })
82 }
83}
84
85impl<F, Digest> MerkleCap<F, Digest> {
86 pub fn new(cap: Vec<Digest>) -> Self {
92 assert!(
94 cap.len().is_power_of_two(),
95 "a Merkle cap holds a power-of-two number of roots, got {}",
96 cap.len()
97 );
98 Self {
99 cap,
100 _marker: PhantomData,
101 }
102 }
103
104 #[must_use]
106 pub const fn num_roots(&self) -> usize {
107 self.cap.len()
108 }
109
110 #[must_use]
113 pub const fn height(&self) -> usize {
114 log2_strict_usize(self.num_roots())
115 }
116
117 #[must_use]
119 pub fn roots(&self) -> &[Digest] {
120 &self.cap
121 }
122
123 pub fn into_roots(self) -> Vec<Digest> {
125 self.cap.into_iter().collect()
126 }
127}
128
129impl<F, Digest> From<Vec<Digest>> for MerkleCap<F, Digest> {
130 fn from(cap: Vec<Digest>) -> Self {
131 Self::new(cap)
132 }
133}
134
135impl<F, W, const N: usize> From<Hash<F, W, N>> for MerkleCap<F, [W; N]> {
136 fn from(hash: Hash<F, W, N>) -> Self {
137 Self::new(vec![hash.into()])
138 }
139}
140
141impl<F, Digest> Borrow<[Digest]> for MerkleCap<F, Digest> {
142 fn borrow(&self) -> &[Digest] {
143 &self.cap
144 }
145}
146
147impl<F, Digest> AsRef<[Digest]> for MerkleCap<F, Digest> {
148 fn as_ref(&self) -> &[Digest] {
149 &self.cap
150 }
151}
152
153impl<F, Digest> core::ops::Index<usize> for MerkleCap<F, Digest> {
154 type Output = Digest;
155
156 fn index(&self, index: usize) -> &Self::Output {
157 &self.cap[index]
158 }
159}
160
161impl<F, Digest> IntoIterator for MerkleCap<F, Digest> {
162 type Item = Digest;
163 type IntoIter = IntoIter<Digest>;
164
165 fn into_iter(self) -> Self::IntoIter {
166 self.cap.into_iter()
167 }
168}
169
170impl<F, W, const DIGEST_ELEMS: usize> From<[W; DIGEST_ELEMS]> for Hash<F, W, DIGEST_ELEMS> {
171 fn from(value: [W; DIGEST_ELEMS]) -> Self {
172 Self {
173 value,
174 _marker: PhantomData,
175 }
176 }
177}
178
179impl<F, W, const DIGEST_ELEMS: usize> From<Hash<F, W, DIGEST_ELEMS>> for [W; DIGEST_ELEMS] {
180 fn from(value: Hash<F, W, DIGEST_ELEMS>) -> [W; DIGEST_ELEMS] {
181 value.value
182 }
183}
184
185impl<F, W: PartialEq, const DIGEST_ELEMS: usize> PartialEq<[W; DIGEST_ELEMS]>
186 for Hash<F, W, DIGEST_ELEMS>
187{
188 fn eq(&self, other: &[W; DIGEST_ELEMS]) -> bool {
189 self.value == *other
190 }
191}
192
193impl<F, W, const DIGEST_ELEMS: usize> IntoIterator for Hash<F, W, DIGEST_ELEMS> {
194 type Item = W;
195 type IntoIter = core::array::IntoIter<W, DIGEST_ELEMS>;
196
197 fn into_iter(self) -> Self::IntoIter {
198 self.value.into_iter()
199 }
200}
201
202impl<F, W, const DIGEST_ELEMS: usize> Borrow<[W; DIGEST_ELEMS]> for Hash<F, W, DIGEST_ELEMS> {
203 fn borrow(&self) -> &[W; DIGEST_ELEMS] {
204 &self.value
205 }
206}
207
208impl<F, W, const DIGEST_ELEMS: usize> AsRef<[W; DIGEST_ELEMS]> for Hash<F, W, DIGEST_ELEMS> {
209 fn as_ref(&self) -> &[W; DIGEST_ELEMS] {
210 &self.value
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use alloc::string::ToString;
217 use alloc::vec;
218
219 use p3_goldilocks::Goldilocks;
220
221 use super::*;
222
223 type F = Goldilocks;
224 type Digest = [u8; 4];
225
226 #[test]
227 fn test_merkle_cap_new_with_power_of_two_sizes() {
228 let cap = MerkleCap::<F, Digest>::new(vec![[7u8; 4]]);
229 assert_eq!(cap.num_roots(), 1);
230 assert_eq!(cap.height(), 0);
231
232 let cap = MerkleCap::<F, Digest>::new(vec![[0u8; 4]; 2]);
233 assert_eq!(cap.num_roots(), 2);
234 assert_eq!(cap.height(), 1);
235
236 let cap = MerkleCap::<F, Digest>::new(vec![[0u8; 4]; 8]);
237 assert_eq!(cap.num_roots(), 8);
238 assert_eq!(cap.height(), 3);
239 }
240
241 #[test]
242 fn test_merkle_cap_wire_shape_is_stable() {
243 let cap = MerkleCap::<F, Digest>::new(vec![[1u8; 4], [2u8; 4], [3u8; 4], [4u8; 4]]);
245
246 let bytes = postcard::to_allocvec(&cap).unwrap();
252 assert_eq!(bytes, [4, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]);
253 let back: MerkleCap<F, Digest> = postcard::from_bytes(&bytes).unwrap();
254 assert_eq!(back, cap);
255 assert_eq!(back.height(), 2);
256
257 let json = serde_json::to_string(&cap).unwrap();
259 assert_eq!(
260 json,
261 r#"{"cap":[[1,1,1,1],[2,2,2,2],[3,3,3,3],[4,4,4,4]],"_marker":null}"#
262 );
263 assert_eq!(
264 serde_json::from_str::<MerkleCap<F, Digest>>(&json).unwrap(),
265 cap
266 );
267 }
268
269 #[test]
270 fn test_merkle_cap_deserialize_rejects_non_power_of_two_root_count() {
271 for (json, message) in [
279 (
280 r#"{"cap":[[1,1,1,1],[2,2,2,2],[3,3,3,3]],"_marker":null}"#,
281 "invalid length 3, expected a power-of-two number of Merkle cap roots",
282 ),
283 (
284 r#"{"cap":[],"_marker":null}"#,
285 "invalid length 0, expected a power-of-two number of Merkle cap roots",
286 ),
287 ] {
288 let err = serde_json::from_str::<MerkleCap<F, Digest>>(json)
289 .expect_err("a cap with a non-power-of-two root count must not deserialize");
290 assert_eq!(err.to_string(), message);
291 }
292 }
293
294 #[test]
295 fn test_merkle_cap_compact_decoding_rejects_a_non_power_of_two_root_count() {
296 for (rejected, accepted, roots) in [
307 (
308 &[3u8, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3][..],
309 &[4u8, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4][..],
310 4,
311 ),
312 (&[0u8][..], &[1u8, 1, 1, 1, 1][..], 1),
313 ] {
314 postcard::from_bytes::<MerkleCap<F, Digest>>(rejected)
315 .expect_err("a cap with a non-power-of-two root count must not deserialize");
316
317 let cap = postcard::from_bytes::<MerkleCap<F, Digest>>(accepted)
318 .expect("a power-of-two root count is accepted");
319 assert_eq!(cap.num_roots(), roots);
320 }
321 }
322
323 #[test]
324 #[should_panic]
325 fn test_merkle_cap_new_panics_on_empty() {
326 let _ = MerkleCap::<F, Digest>::new(vec![]);
327 }
328
329 #[test]
330 #[should_panic]
331 fn test_merkle_cap_new_panics_on_three() {
332 let _ = MerkleCap::<F, Digest>::new(vec![[0u8; 4]; 3]);
333 }
334
335 #[test]
336 #[should_panic]
337 fn test_merkle_cap_from_vec_panics_on_empty() {
338 let _: MerkleCap<F, Digest> = vec![].into();
339 }
340
341 #[test]
342 fn test_merkle_cap_from_hash() {
343 let hash = Hash::<F, u8, 4>::from([1u8, 2, 3, 4]);
344 let cap: MerkleCap<F, [u8; 4]> = hash.into();
345 assert_eq!(cap.num_roots(), 1);
346 assert_eq!(cap.height(), 0);
347 }
348}