Skip to main content

miden_objects/conversion/
merkle.rs

1use alloc::vec::Vec;
2
3use miden_protocol::Word;
4use miden_protocol::crypto::merkle::mmr::{MmrDelta, PartialMmr};
5use miden_protocol::crypto::merkle::smt::{PartialSmt, SmtLeaf, SmtProof, UniqueNodes};
6use miden_protocol::crypto::merkle::{MerklePath, SparseMerklePath};
7
8use crate::proto;
9
10#[cfg(test)]
11mod tests;
12
13// MERKLE PATH
14// ================================================================================================
15
16impl From<&MerklePath> for proto::primitives::MerklePath {
17    fn from(value: &MerklePath) -> Self {
18        let siblings = value.nodes().iter().map(Into::into).collect();
19        proto::primitives::MerklePath { siblings }
20    }
21}
22
23impl From<MerklePath> for proto::primitives::MerklePath {
24    fn from(value: MerklePath) -> Self {
25        (&value).into()
26    }
27}
28
29// SPARSE MERKLE PATH
30// ================================================================================================
31
32impl From<SparseMerklePath> for proto::primitives::SparseMerklePath {
33    fn from(value: SparseMerklePath) -> Self {
34        let (empty_nodes_mask, siblings) = value.into_parts();
35        proto::primitives::SparseMerklePath {
36            empty_nodes_mask,
37            siblings: siblings.into_iter().map(Into::into).collect(),
38        }
39    }
40}
41
42// PARTIAL MMR
43// ================================================================================================
44
45impl From<&PartialMmr> for proto::primitives::PartialMmr {
46    fn from(mmr: &PartialMmr) -> Self {
47        let tracked_leaves = mmr
48            .leaves()
49            .map(|(position, leaf)| {
50                let proof = mmr
51                    .open(position)
52                    .expect("tracked MMR position must be in bounds")
53                    .expect("tracked MMR leaf must have an opening");
54                proto::primitives::TrackedMmrLeaf {
55                    position: position as u64,
56                    leaf: Some(leaf.into()),
57                    path: proof.merkle_path().nodes().iter().map(Into::into).collect(),
58                }
59            })
60            .collect();
61        Self {
62            forest: mmr.forest().num_leaves() as u64,
63            peaks: mmr.peaks().peaks().iter().map(Into::into).collect(),
64            tracked_leaves,
65        }
66    }
67}
68
69impl From<PartialMmr> for proto::primitives::PartialMmr {
70    fn from(mmr: PartialMmr) -> Self {
71        (&mmr).into()
72    }
73}
74
75// MMR DELTA
76// ================================================================================================
77
78impl From<MmrDelta> for proto::primitives::MmrDelta {
79    fn from(value: MmrDelta) -> Self {
80        let update_data = value.data.into_iter().map(Into::into).collect();
81        proto::primitives::MmrDelta {
82            forest: value.forest.num_leaves() as u64,
83            update_data,
84        }
85    }
86}
87
88// SPARSE MERKLE TREE
89// ================================================================================================
90
91// SMT LEAF
92// ------------------------------------------------------------------------------------------------
93
94impl From<SmtLeaf> for proto::primitives::SmtLeaf {
95    fn from(smt_leaf: SmtLeaf) -> Self {
96        use proto::primitives::smt_leaf::Leaf;
97
98        let leaf = match smt_leaf {
99            SmtLeaf::Empty(leaf_index) => Leaf::EmptyLeafIndex(leaf_index.position()),
100            SmtLeaf::Single(entry) => Leaf::Single(entry.into()),
101            SmtLeaf::Multiple(entries) => Leaf::Multiple(proto::primitives::SmtLeafEntryList {
102                entries: entries.into_iter().map(Into::into).collect(),
103            }),
104        };
105
106        Self { leaf: Some(leaf) }
107    }
108}
109
110// SMT LEAF ENTRY
111// ------------------------------------------------------------------------------------------------
112
113impl From<(Word, Word)> for proto::primitives::SmtLeafEntry {
114    fn from((key, value): (Word, Word)) -> Self {
115        Self {
116            key: Some(key.into()),
117            value: Some(value.into()),
118        }
119    }
120}
121
122// SMT PROOF
123// ------------------------------------------------------------------------------------------------
124
125impl From<SmtProof> for proto::primitives::SmtOpening {
126    fn from(proof: SmtProof) -> Self {
127        let (path, leaf) = proof.into_parts();
128        Self {
129            path: Some(path.into()),
130            leaf: Some(leaf.into()),
131        }
132    }
133}
134
135// PARTIAL SMT
136// ------------------------------------------------------------------------------------------------
137
138impl From<UniqueNodes> for proto::primitives::PartialSmt {
139    fn from(unique_nodes: UniqueNodes) -> Self {
140        let UniqueNodes { root, nodes, leaves, value_only_leaves } = unique_nodes;
141
142        let mut node_levels = Vec::new();
143        let mut nodes = nodes.into_iter().peekable();
144        while let Some((index, _)) = nodes.peek() {
145            let depth = index.depth();
146            let mut level_nodes = Vec::new();
147            while let Some((index, digest)) = nodes.next_if(|(index, _)| index.depth() == depth) {
148                level_nodes.push(proto::primitives::PartialSmtNode {
149                    index: index.position(),
150                    digest: Some(digest.into()),
151                });
152            }
153            node_levels.push(proto::primitives::PartialSmtNodeLevel {
154                depth: u32::from(depth),
155                nodes: level_nodes,
156            });
157        }
158        let leaves = leaves
159            .into_iter()
160            .map(|(index, leaf)| proto::primitives::IndexedSmtLeaf {
161                index,
162                leaf: Some(leaf.into()),
163            })
164            .collect();
165
166        let value_only_leaves = value_only_leaves
167            .into_iter()
168            .map(|(index, value)| proto::primitives::IndexedDigest {
169                index,
170                value: Some(value.into()),
171            })
172            .collect();
173
174        Self {
175            root: Some(root.into()),
176            node_levels,
177            leaves,
178            value_only_leaves,
179        }
180    }
181}
182
183impl From<PartialSmt> for proto::primitives::PartialSmt {
184    fn from(partial_smt: PartialSmt) -> Self {
185        partial_smt.to_unique_nodes().into()
186    }
187}