miden_objects/block/
note_tree.rs1use alloc::string::ToString;
2
3use crate::{
4 BLOCK_NOTE_TREE_DEPTH, MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH,
5 MAX_OUTPUT_NOTES_PER_BLOCK,
6 batch::BatchNoteTree,
7 crypto::{
8 hash::rpo::RpoDigest,
9 merkle::{LeafIndex, MerkleError, MerklePath, SimpleSmt},
10 },
11 note::{NoteId, NoteMetadata, compute_note_commitment},
12 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
13};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct BlockNoteTree(SimpleSmt<BLOCK_NOTE_TREE_DEPTH>);
22
23impl BlockNoteTree {
24 pub fn with_entries(
37 entries: impl IntoIterator<Item = (BlockNoteIndex, NoteId, NoteMetadata)>,
38 ) -> Result<Self, MerkleError> {
39 let leaves = entries.into_iter().map(|(index, note_id, metadata)| {
40 (
41 index.leaf_index_value() as u64,
42 compute_note_commitment(note_id, &metadata).into(),
43 )
44 });
45
46 SimpleSmt::with_leaves(leaves).map(Self)
47 }
48
49 pub fn empty() -> Self {
51 Self(SimpleSmt::new().expect("depth should be 16 and thus > 0 and <= 64"))
52 }
53
54 pub fn insert_batch_note_subtree(
62 &mut self,
63 batch_idx: u64,
64 batch_note_tree: BatchNoteTree,
65 ) -> Result<(), MerkleError> {
66 self.0.set_subtree(batch_idx, batch_note_tree.into_smt()).map(|_| ())
70 }
71
72 pub fn root(&self) -> RpoDigest {
74 self.0.root()
75 }
76
77 pub fn get_note_path(&self, index: BlockNoteIndex) -> MerklePath {
79 self.0.open(&index.leaf_index()).path
81 }
82
83 pub fn num_notes(&self) -> usize {
85 self.0.num_leaves()
86 }
87
88 pub fn is_empty(&self) -> bool {
90 self.0.is_empty()
91 }
92}
93
94impl Default for BlockNoteTree {
95 fn default() -> Self {
96 Self(SimpleSmt::new().expect("Unreachable"))
97 }
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub struct BlockNoteIndex {
106 batch_idx: usize,
107 note_idx_in_batch: usize,
108}
109
110impl BlockNoteIndex {
111 pub fn new(batch_idx: usize, note_idx_in_batch: usize) -> Option<Self> {
118 if batch_idx >= MAX_BATCHES_PER_BLOCK || note_idx_in_batch >= MAX_OUTPUT_NOTES_PER_BATCH {
119 return None;
120 }
121
122 Some(Self { batch_idx, note_idx_in_batch })
123 }
124
125 pub fn batch_idx(&self) -> usize {
127 self.batch_idx
128 }
129
130 pub fn note_idx_in_batch(&self) -> usize {
132 self.note_idx_in_batch
133 }
134
135 pub fn leaf_index(&self) -> LeafIndex<BLOCK_NOTE_TREE_DEPTH> {
137 LeafIndex::new(
138 (self.batch_idx() * MAX_OUTPUT_NOTES_PER_BATCH + self.note_idx_in_batch()) as u64,
139 )
140 .expect("Unreachable: Input values must be valid at this point")
141 }
142
143 pub fn leaf_index_value(&self) -> u16 {
145 const _: () = assert!(
146 MAX_OUTPUT_NOTES_PER_BLOCK <= u16::MAX as usize + 1,
147 "Any note index is expected to fit in `u16`"
148 );
149
150 self.leaf_index()
151 .value()
152 .try_into()
153 .expect("Unreachable: Input values must be valid at this point")
154 }
155}
156
157impl Serializable for BlockNoteTree {
161 fn write_into<W: ByteWriter>(&self, target: &mut W) {
162 target.write_u32(self.0.num_leaves() as u32);
163 target.write_many(self.0.leaves());
164 }
165}
166
167impl Deserializable for BlockNoteTree {
168 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
169 let count = source.read_u32()?;
170 let leaves = source.read_many(count as usize)?;
171
172 SimpleSmt::with_leaves(leaves)
173 .map(Self)
174 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use miden_crypto::{
181 Felt, ONE, ZERO,
182 merkle::SimpleSmt,
183 utils::{Deserializable, Serializable},
184 };
185
186 use super::BlockNoteTree;
187
188 #[test]
189 fn test_serialization() {
190 let data = core::iter::repeat(())
191 .enumerate()
192 .map(|(idx, ())| (idx as u64, [ONE, ZERO, ONE, Felt::new(idx as u64)]))
193 .take(100);
194 let initial_tree = BlockNoteTree(SimpleSmt::with_leaves(data).unwrap());
195
196 let serialized = initial_tree.to_bytes();
197 let deserialized_tree = BlockNoteTree::read_from_bytes(&serialized).unwrap();
198
199 assert_eq!(deserialized_tree, initial_tree);
200 }
201}