1use ark_serialize::{
12 CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
13};
14use ark_std::io::{Read, Write};
15use jf_merkle_tree::{DigestAlgorithm, errors::MerkleTreeError};
16use tagged_base64::tagged;
17
18const LEAF_HASH_DOM_SEP: &[u8; 1] = b"1";
21const INTERNAL_HASH_DOM_SEP: &[u8; 1] = b"0";
22
23#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq, Ord, PartialOrd)]
25#[tagged("HASH")]
26#[repr(transparent)]
27pub struct Blake3Node([u8; 32]);
28
29impl Blake3Node {
30 pub fn new(bytes: [u8; 32]) -> Self {
32 Self(bytes)
33 }
34}
35
36impl From<blake3::Hash> for Blake3Node {
37 fn from(h: blake3::Hash) -> Self {
38 Self(*h.as_bytes())
39 }
40}
41
42impl AsRef<[u8]> for Blake3Node {
43 fn as_ref(&self) -> &[u8] {
44 &self.0
45 }
46}
47
48impl AsRef<[u8; 32]> for Blake3Node {
49 fn as_ref(&self) -> &[u8; 32] {
50 &self.0
51 }
52}
53
54impl CanonicalSerialize for Blake3Node {
55 fn serialize_with_mode<W: Write>(
56 &self,
57 mut writer: W,
58 _compress: Compress,
59 ) -> Result<(), SerializationError> {
60 writer.write_all(&self.0)?;
61 Ok(())
62 }
63
64 fn serialized_size(&self, _compress: Compress) -> usize {
65 32
66 }
67}
68
69impl CanonicalDeserialize for Blake3Node {
70 fn deserialize_with_mode<R: Read>(
71 mut reader: R,
72 _compress: Compress,
73 _validate: Validate,
74 ) -> Result<Self, SerializationError> {
75 let mut buf = [0u8; 32];
76 reader.read_exact(&mut buf)?;
77 Ok(Self(buf))
78 }
79}
80
81impl Valid for Blake3Node {
82 fn check(&self) -> Result<(), SerializationError> {
83 Ok(())
84 }
85}
86
87pub struct Blake3DigestAlgorithm;
89
90impl<E, I> DigestAlgorithm<E, I, Blake3Node> for Blake3DigestAlgorithm
91where
92 E: jf_merkle_tree::Element + CanonicalSerialize,
93 I: jf_merkle_tree::Index + CanonicalSerialize,
94{
95 fn digest(data: &[Blake3Node]) -> Result<Blake3Node, MerkleTreeError> {
96 let mut hasher = blake3::Hasher::new();
97 hasher.update(INTERNAL_HASH_DOM_SEP);
98 for v in data {
99 hasher.update(&v.0);
100 }
101 Ok(Blake3Node::from(hasher.finalize()))
102 }
103
104 fn digest_leaf(pos: &I, elem: &E) -> Result<Blake3Node, MerkleTreeError> {
105 let mut hasher = blake3::Hasher::new();
106 hasher.update(LEAF_HASH_DOM_SEP);
107 let mut adapter = HasherWriter(&mut hasher);
108 pos.serialize_uncompressed(&mut adapter)
109 .map_err(|_| MerkleTreeError::DigestError("Failed serializing pos".into()))?;
110 elem.serialize_uncompressed(&mut adapter)
111 .map_err(|_| MerkleTreeError::DigestError("Failed serializing elem".into()))?;
112 Ok(Blake3Node::from(hasher.finalize()))
113 }
114}
115
116struct HasherWriter<'a>(&'a mut blake3::Hasher);
122
123impl Write for HasherWriter<'_> {
124 fn write(&mut self, buf: &[u8]) -> ark_std::io::Result<usize> {
125 self.0.update(buf);
126 Ok(buf.len())
127 }
128
129 fn flush(&mut self) -> ark_std::io::Result<()> {
130 Ok(())
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use jf_merkle_tree::{MerkleTreeScheme, append_only::MerkleTree as JfMerkleTree};
137
138 use super::*;
139
140 type Mt = JfMerkleTree<Blake3Node, Blake3DigestAlgorithm, u64, 4, Blake3Node>;
141
142 fn leaf(i: u8) -> Blake3Node {
143 let mut buf = [0u8; 32];
144 buf[0] = i;
145 Blake3Node::new(buf)
146 }
147
148 #[test]
150 fn deterministic_commitment() {
151 let leaves: Vec<Blake3Node> = (0u8..16).map(leaf).collect();
152 let a = Mt::from_elems(None, &leaves).unwrap().commitment();
153 let b = Mt::from_elems(None, &leaves).unwrap().commitment();
154 assert_eq!(a, b);
155 }
156
157 #[test]
159 fn proof_round_trip() {
160 let leaves: Vec<Blake3Node> = (0u8..16).map(leaf).collect();
161 let mt = Mt::from_elems(None, &leaves).unwrap();
162 let commit = mt.commitment();
163 for k in 0u64..16 {
164 let (val, proof) = mt.lookup(k).expect_ok().unwrap();
165 assert_eq!(*val, leaves[k as usize]);
166 assert!(Mt::verify(commit, k, *val, &proof).unwrap().is_ok());
167 }
168 }
169
170 #[test]
172 fn proof_rejects_tampered_leaf() {
173 let leaves: Vec<Blake3Node> = (0u8..16).map(leaf).collect();
174 let mt = Mt::from_elems(None, &leaves).unwrap();
175 let commit = mt.commitment();
176 let (_, proof) = mt.lookup(0).expect_ok().unwrap();
177 let bad = leaf(99);
178 assert!(Mt::verify(commit, 0u64, bad, &proof).unwrap().is_err());
179 }
180
181 #[test]
183 fn canonical_serialize_round_trip() {
184 let n = Blake3Node::new([7u8; 32]);
185 let mut buf = Vec::new();
186 n.serialize_uncompressed(&mut buf).unwrap();
187 assert_eq!(buf.len(), 32);
188 assert_eq!(buf, vec![7u8; 32]);
189 let n2 = Blake3Node::deserialize_uncompressed(&buf[..]).unwrap();
190 assert_eq!(n, n2);
191 }
192}