Skip to main content

miden_objects/conversion/
primitives.rs

1use alloc::collections::BTreeMap;
2use alloc::format;
3use alloc::vec::Vec;
4
5use miden_protocol::crypto::dsa::ecdsa_k256_keccak::{PublicKey, Signature};
6use miden_protocol::crypto::merkle::store::MerkleStore;
7use miden_protocol::utils::serde::{Deserializable, DeserializationError, Serializable};
8use miden_protocol::vm::{AdviceInputs, AdviceMap, AdviceStack, ExecutionProof};
9use miden_protocol::{Felt, MastForest, Word};
10
11use crate::{ConversionError, proto};
12
13#[cfg(test)]
14mod tests;
15
16// FELT
17// ================================================================================================
18
19impl From<Felt> for proto::primitives::Felt {
20    fn from(value: Felt) -> Self {
21        Self { value: value.as_canonical_u64() }
22    }
23}
24
25impl From<&Felt> for proto::primitives::Felt {
26    fn from(value: &Felt) -> Self {
27        Self { value: value.as_canonical_u64() }
28    }
29}
30
31impl TryFrom<proto::primitives::Felt> for Felt {
32    type Error = ConversionError;
33
34    fn try_from(value: proto::primitives::Felt) -> Result<Self, Self::Error> {
35        Self::try_from(&value)
36    }
37}
38
39impl TryFrom<&proto::primitives::Felt> for Felt {
40    type Error = ConversionError;
41
42    fn try_from(value: &proto::primitives::Felt) -> Result<Self, Self::Error> {
43        value.decode_value(|value| Self::try_from(*value))
44    }
45}
46
47// WORD
48// ================================================================================================
49
50impl From<Word> for proto::primitives::Word {
51    fn from(value: Word) -> Self {
52        Self { encoded: value.to_bytes() }
53    }
54}
55
56impl From<&Word> for proto::primitives::Word {
57    fn from(value: &Word) -> Self {
58        Self { encoded: value.to_bytes() }
59    }
60}
61
62impl TryFrom<proto::primitives::Word> for Word {
63    type Error = ConversionError;
64
65    fn try_from(value: proto::primitives::Word) -> Result<Self, Self::Error> {
66        Self::try_from(&value)
67    }
68}
69
70impl TryFrom<&proto::primitives::Word> for Word {
71    type Error = ConversionError;
72
73    fn try_from(value: &proto::primitives::Word) -> Result<Self, Self::Error> {
74        value.decode_value(|encoded| {
75            if encoded.len() != Word::SERIALIZED_SIZE {
76                return Err(DeserializationError::InvalidValue(format!(
77                    "expected exactly {} bytes, got {}",
78                    Word::SERIALIZED_SIZE,
79                    encoded.len()
80                )));
81            }
82            Self::read_from_bytes(encoded)
83        })
84    }
85}
86
87// EXECUTION PROOF
88// ================================================================================================
89
90impl From<&ExecutionProof> for proto::primitives::ExecutionProof {
91    fn from(value: &ExecutionProof) -> Self {
92        Self { encoded: value.to_bytes() }
93    }
94}
95
96impl From<ExecutionProof> for proto::primitives::ExecutionProof {
97    fn from(value: ExecutionProof) -> Self {
98        (&value).into()
99    }
100}
101
102impl TryFrom<proto::primitives::ExecutionProof> for ExecutionProof {
103    type Error = ConversionError;
104
105    fn try_from(value: proto::primitives::ExecutionProof) -> Result<Self, Self::Error> {
106        Self::try_from(&value)
107    }
108}
109
110impl TryFrom<&proto::primitives::ExecutionProof> for ExecutionProof {
111    type Error = ConversionError;
112
113    fn try_from(value: &proto::primitives::ExecutionProof) -> Result<Self, Self::Error> {
114        value.decode_value(|encoded| Self::read_from_bytes(encoded))
115    }
116}
117
118// MAST FOREST
119// ================================================================================================
120
121impl From<&MastForest> for proto::primitives::MastForest {
122    fn from(forest: &MastForest) -> Self {
123        let mut encoded = Vec::new();
124        forest.write_hashless(&mut encoded);
125        Self { encoded }
126    }
127}
128
129impl From<MastForest> for proto::primitives::MastForest {
130    fn from(value: MastForest) -> Self {
131        (&value).into()
132    }
133}
134
135// ADVICE INPUTS
136// ================================================================================================
137
138impl From<&AdviceStack> for proto::primitives::AdviceStack {
139    fn from(value: &AdviceStack) -> Self {
140        Self {
141            values: value.iter().map(Into::into).collect(),
142        }
143    }
144}
145
146impl From<&AdviceMap> for proto::primitives::AdviceMap {
147    fn from(value: &AdviceMap) -> Self {
148        Self {
149            entries: value
150                .iter()
151                .map(|(key, values)| proto::primitives::AdviceMapEntry {
152                    key: Some(key.into()),
153                    values: values.iter().map(Into::into).collect(),
154                })
155                .collect(),
156        }
157    }
158}
159
160impl From<&MerkleStore> for proto::primitives::MerkleStore {
161    fn from(value: &MerkleStore) -> Self {
162        let default_nodes = MerkleStore::new()
163            .inner_nodes()
164            .map(|node| (node.value, (node.left, node.right)))
165            .collect::<BTreeMap<_, _>>();
166        let mut nodes = value
167            .inner_nodes()
168            .filter(|node| default_nodes.get(&node.value) != Some(&(node.left, node.right)))
169            .collect::<Vec<_>>();
170        nodes.sort_by_key(|node| node.value);
171
172        Self {
173            nodes: nodes
174                .into_iter()
175                .map(|node| proto::primitives::MerkleStoreNode {
176                    value: Some(node.value.into()),
177                    left: Some(node.left.into()),
178                    right: Some(node.right.into()),
179                })
180                .collect(),
181        }
182    }
183}
184
185impl From<&AdviceInputs> for proto::primitives::AdviceInputs {
186    fn from(value: &AdviceInputs) -> Self {
187        Self {
188            advice_stack: Some((&value.stack()).into()),
189            advice_map: Some(value.map().into()),
190            merkle_store: Some(value.store().into()),
191        }
192    }
193}
194
195// PUBLIC KEY
196// ================================================================================================
197
198impl From<&PublicKey> for proto::primitives::PublicKey {
199    fn from(value: &PublicKey) -> Self {
200        Self {
201            key: Some(proto::primitives::public_key::Key::EcdsaK256Keccak(value.to_bytes())),
202        }
203    }
204}
205
206impl From<PublicKey> for proto::primitives::PublicKey {
207    fn from(value: PublicKey) -> Self {
208        (&value).into()
209    }
210}
211
212// SIGNATURE
213// ================================================================================================
214
215impl From<&Signature> for proto::primitives::Signature {
216    fn from(value: &Signature) -> Self {
217        Self {
218            signature: Some(proto::primitives::signature::Signature::EcdsaK256Keccak(
219                value.to_bytes(),
220            )),
221        }
222    }
223}
224
225impl From<Signature> for proto::primitives::Signature {
226    fn from(value: Signature) -> Self {
227        (&value).into()
228    }
229}
230
231// Canonical representation adapter; domain interpretation is left to the containing record.
232impl crate::DecodeMessage for proto::primitives::Word {
233    type Decoded = miden_protocol::Word;
234}
235
236// Canonical representation adapter; domain interpretation is left to the containing record.
237impl crate::DecodeMessage for proto::primitives::Felt {
238    type Decoded = miden_protocol::Felt;
239}
240
241// Canonical representation adapter; domain interpretation is left to the containing record.
242impl crate::DecodeMessage for proto::primitives::ExecutionProof {
243    type Decoded = miden_protocol::vm::ExecutionProof;
244}