Skip to main content

miden_client/rpc/domain/
smt.rs

1use alloc::string::ToString;
2
3use miden_protocol::Word;
4use miden_protocol::crypto::merkle::smt::{LeafIndex, SMT_DEPTH, SmtLeaf, SmtProof};
5
6use crate::rpc::domain::MissingFieldHelper;
7use crate::rpc::errors::RpcConversionError;
8use crate::rpc::generated as proto;
9
10// SMT LEAF ENTRY
11// ================================================================================================
12
13impl From<&(Word, Word)> for proto::primitives::SmtLeafEntry {
14    fn from(value: &(Word, Word)) -> Self {
15        proto::primitives::SmtLeafEntry {
16            key: Some(value.0.into()),
17            value: Some(value.1.into()),
18        }
19    }
20}
21
22impl TryFrom<&proto::primitives::SmtLeafEntry> for (Word, Word) {
23    type Error = RpcConversionError;
24
25    fn try_from(value: &proto::primitives::SmtLeafEntry) -> Result<Self, Self::Error> {
26        let key = match value.key {
27            Some(key) => key.try_into()?,
28            None => return Err(proto::primitives::SmtLeafEntry::missing_field(stringify!(key))),
29        };
30
31        let value: Word = match value.value {
32            Some(value) => value.try_into()?,
33            None => return Err(proto::primitives::SmtLeafEntry::missing_field(stringify!(value))),
34        };
35
36        Ok((key, value))
37    }
38}
39
40// SMT LEAF
41// ================================================================================================
42
43impl From<SmtLeaf> for proto::primitives::SmtLeaf {
44    fn from(value: SmtLeaf) -> Self {
45        (&value).into()
46    }
47}
48
49impl From<&SmtLeaf> for proto::primitives::SmtLeaf {
50    fn from(value: &SmtLeaf) -> Self {
51        match value {
52            SmtLeaf::Empty(index) => proto::primitives::SmtLeaf {
53                leaf: Some(proto::primitives::smt_leaf::Leaf::EmptyLeafIndex(index.value())),
54            },
55            SmtLeaf::Single(entry) => proto::primitives::SmtLeaf {
56                leaf: Some(proto::primitives::smt_leaf::Leaf::Single(entry.into())),
57            },
58            SmtLeaf::Multiple(entries) => proto::primitives::SmtLeaf {
59                leaf: Some(proto::primitives::smt_leaf::Leaf::Multiple(
60                    proto::primitives::SmtLeafEntryList {
61                        entries: entries.iter().map(Into::into).collect(),
62                    },
63                )),
64            },
65        }
66    }
67}
68
69impl TryFrom<&proto::primitives::SmtLeaf> for SmtLeaf {
70    type Error = RpcConversionError;
71
72    fn try_from(value: &proto::primitives::SmtLeaf) -> Result<Self, Self::Error> {
73        match &value.leaf {
74            Some(proto::primitives::smt_leaf::Leaf::EmptyLeafIndex(index)) => Ok(SmtLeaf::Empty(
75                LeafIndex::<SMT_DEPTH>::new(*index)
76                    .map_err(|err| RpcConversionError::InvalidField(err.to_string()))?,
77            )),
78            Some(proto::primitives::smt_leaf::Leaf::Single(entry)) => {
79                Ok(SmtLeaf::Single(entry.try_into()?))
80            },
81            Some(proto::primitives::smt_leaf::Leaf::Multiple(entries)) => {
82                let entries =
83                    entries.entries.iter().map(TryInto::try_into).collect::<Result<_, _>>()?;
84                Ok(SmtLeaf::Multiple(entries))
85            },
86            None => Err(proto::primitives::SmtLeaf::missing_field(stringify!(leaf))),
87        }
88    }
89}
90
91// SMT PROOF
92// ================================================================================================
93
94impl From<SmtProof> for proto::primitives::SmtOpening {
95    fn from(value: SmtProof) -> Self {
96        let (path, leaf) = value.into_parts();
97
98        proto::primitives::SmtOpening {
99            leaf: Some(leaf.into()),
100            path: Some(path.into()),
101        }
102    }
103}
104
105impl TryFrom<proto::primitives::SmtOpening> for SmtProof {
106    type Error = RpcConversionError;
107
108    fn try_from(value: proto::primitives::SmtOpening) -> Result<Self, Self::Error> {
109        let leaf = match &value.leaf {
110            Some(leaf) => leaf.try_into()?,
111            None => return Err(proto::primitives::SmtOpening::missing_field(stringify!(leaf))),
112        };
113
114        let path = match value.path {
115            Some(path) => path.try_into()?,
116            None => return Err(proto::primitives::SmtOpening::missing_field(stringify!(path))),
117        };
118
119        SmtProof::new(path, leaf).map_err(|err| RpcConversionError::InvalidField(err.to_string()))
120    }
121}