celestia_types/nmt/
namespaced_hash.rs1use crate::nmt::{NS_SIZE, NamespacedHash, NamespacedSha2Hasher};
2use crate::{Error, Result};
3
4use nmt_rs::simple_merkle::tree::MerkleHash;
5
6pub const NAMESPACED_HASH_SIZE: usize = NamespacedHash::size();
8pub const HASH_SIZE: usize = 32;
10
11pub type RawNamespacedHash = [u8; NAMESPACED_HASH_SIZE];
13
14pub trait NamespacedHashExt {
16 fn empty_root() -> NamespacedHash;
20 fn from_raw(bytes: &[u8]) -> Result<NamespacedHash>;
22 fn to_vec(&self) -> Vec<u8>;
24 fn to_array(&self) -> RawNamespacedHash;
26 fn validate_namespace_order(&self) -> Result<()>;
33}
34
35impl NamespacedHashExt for NamespacedHash {
36 fn empty_root() -> NamespacedHash {
37 NamespacedSha2Hasher::EMPTY_ROOT
38 }
39
40 fn from_raw(bytes: &[u8]) -> Result<NamespacedHash> {
41 Ok(bytes.try_into()?)
42 }
43
44 fn to_vec(&self) -> Vec<u8> {
45 self.iter().collect()
46 }
47
48 fn to_array(&self) -> RawNamespacedHash {
49 let mut out = [0; NAMESPACED_HASH_SIZE];
50 out[..NS_SIZE].copy_from_slice(&self.min_namespace().0);
51 out[NS_SIZE..2 * NS_SIZE].copy_from_slice(&self.max_namespace().0);
52 out[2 * NS_SIZE..].copy_from_slice(&self.hash());
53 out
54 }
55
56 fn validate_namespace_order(&self) -> Result<()> {
57 if self.min_namespace() > self.max_namespace() {
58 return Err(Error::InvalidNmtNodeOrder);
59 }
60
61 Ok(())
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::nmt::{NS_ID_V0_SIZE, Namespace};
69
70 #[test]
71 fn namespaced_hash_validate_namespace_order() {
72 let n0 = Namespace::new_v0(&[1]).unwrap();
73 let n1 = Namespace::new_v0(&[2]).unwrap();
74
75 assert!(
76 NamespacedHash::with_min_and_max_ns(*n0, *n1)
77 .validate_namespace_order()
78 .is_ok()
79 );
80 assert!(
81 NamespacedHash::with_min_and_max_ns(*n1, *n1)
82 .validate_namespace_order()
83 .is_ok()
84 );
85 assert!(
86 NamespacedHash::with_min_and_max_ns(*n1, *n0)
87 .validate_namespace_order()
88 .is_err()
89 );
90 }
91
92 #[test]
93 fn hash_to_array() {
94 let ns_min = [9; NS_ID_V0_SIZE];
95 let ns_max = [2; NS_ID_V0_SIZE];
96
97 let mut ns_bytes_min = [0; NS_SIZE];
98 ns_bytes_min[NS_SIZE - NS_ID_V0_SIZE..].copy_from_slice(&ns_min);
99 let mut ns_bytes_max = [0; NS_SIZE];
100 ns_bytes_max[NS_SIZE - NS_ID_V0_SIZE..].copy_from_slice(&ns_max);
101
102 let buff = NamespacedHash::with_min_and_max_ns(
103 *Namespace::new_v0(&ns_min).unwrap(),
104 *Namespace::new_v0(&ns_max).unwrap(),
105 )
106 .to_array();
107
108 assert_eq!(buff[..NS_SIZE], ns_bytes_min);
109 assert_eq!(buff[NS_SIZE..NS_SIZE * 2], ns_bytes_max);
110 assert_eq!(buff[NS_SIZE * 2..], [0; HASH_SIZE]);
111 }
112}