miden_processor/host/advice/mod.rs
1use alloc::{
2 collections::{BTreeMap, btree_map::Entry},
3 vec::Vec,
4};
5
6use miden_core::{
7 AdviceMap, Felt, Word,
8 crypto::merkle::{InnerNodeInfo, MerklePath, MerkleStore, NodeIndex, StoreNode},
9};
10
11mod inputs;
12pub use inputs::AdviceInputs;
13
14mod errors;
15pub use errors::AdviceError;
16
17use crate::host::AdviceMutation;
18
19// TYPE ALIASES
20// ================================================================================================
21
22type SimpleMerkleMap = BTreeMap<Word, StoreNode>;
23
24// ADVICE PROVIDER
25// ================================================================================================
26
27/// An advice provider is a component through which the host can interact with the advice provider.
28/// The host can request nondeterministic inputs from the advice provider (i.e., result of a
29/// computation performed outside of the VM), as well as insert new data into the advice provider.
30///
31/// An advice provider consists of the following components:
32/// 1. Advice stack, which is a LIFO data structure. The processor can move the elements from the
33/// advice stack onto the operand stack, as well as push new elements onto the advice stack.
34/// 2. Advice map, which is a key-value map where keys are words (4 field elements) and values are
35/// vectors of field elements. The processor can push the values from the map onto the advice
36/// stack, as well as insert new values into the map.
37/// 3. Merkle store, which contains structured data reducible to Merkle paths. The VM can request
38/// Merkle paths from the store, as well as mutate it by updating or merging nodes contained in
39/// the store.
40///
41/// Advice data is store in-memory using [BTreeMap]s as its backing storage.
42#[derive(Debug, Clone, Default)]
43pub struct AdviceProvider {
44 stack: Vec<Felt>,
45 map: AdviceMap,
46 store: MerkleStore<SimpleMerkleMap>,
47}
48
49impl AdviceProvider {
50 /// Apply the mutations given in order to the `AdviceProvider`.
51 pub fn apply_mutations(
52 &mut self,
53 mutations: impl IntoIterator<Item = AdviceMutation>,
54 ) -> Result<(), AdviceError> {
55 mutations.into_iter().try_for_each(|mutation| self.apply_mutation(mutation))
56 }
57
58 fn apply_mutation(&mut self, mutation: AdviceMutation) -> Result<(), AdviceError> {
59 match mutation {
60 AdviceMutation::ExtendStack { values } => {
61 self.extend_stack(values);
62 },
63 AdviceMutation::ExtendMap { other } => {
64 self.extend_map(&other)?;
65 },
66 AdviceMutation::ExtendMerkleStore { infos } => {
67 self.extend_merkle_store(infos);
68 },
69 }
70 Ok(())
71 }
72
73 // ADVICE STACK
74 // --------------------------------------------------------------------------------------------
75
76 /// Pops an element from the advice stack and returns it.
77 ///
78 /// # Errors
79 /// Returns an error if the advice stack is empty.
80 pub fn pop_stack(&mut self) -> Result<Felt, AdviceError> {
81 self.stack.pop().ok_or(AdviceError::StackReadFailed)
82 }
83
84 /// Pops a word (4 elements) from the advice stack and returns it.
85 ///
86 /// Note: a word is popped off the stack element-by-element. For example, a `[d, c, b, a, ...]`
87 /// stack (i.e., `d` is at the top of the stack) will yield `[d, c, b, a]`.
88 ///
89 /// # Errors
90 /// Returns an error if the advice stack does not contain a full word.
91 pub fn pop_stack_word(&mut self) -> Result<Word, AdviceError> {
92 if self.stack.len() < 4 {
93 return Err(AdviceError::StackReadFailed);
94 }
95
96 let idx = self.stack.len() - 4;
97 let result =
98 [self.stack[idx + 3], self.stack[idx + 2], self.stack[idx + 1], self.stack[idx]];
99
100 self.stack.truncate(idx);
101
102 Ok(result.into())
103 }
104
105 /// Pops a double word (8 elements) from the advice stack and returns them.
106 ///
107 /// Note: words are popped off the stack element-by-element. For example, a
108 /// `[h, g, f, e, d, c, b, a, ...]` stack (i.e., `h` is at the top of the stack) will yield
109 /// two words: `[h, g, f,e ], [d, c, b, a]`.
110 ///
111 /// # Errors
112 /// Returns an error if the advice stack does not contain two words.
113 pub fn pop_stack_dword(&mut self) -> Result<[Word; 2], AdviceError> {
114 let word0 = self.pop_stack_word()?;
115 let word1 = self.pop_stack_word()?;
116
117 Ok([word0, word1])
118 }
119
120 /// Pushes a single value onto the advice stack.
121 pub fn push_stack(&mut self, value: Felt) {
122 self.stack.push(value)
123 }
124
125 /// Pushes a word (4 elements) onto the stack.
126 pub fn push_stack_word(&mut self, word: &Word) {
127 self.stack.extend(word.iter().rev())
128 }
129
130 /// Fetches a list of elements under the specified key from the advice map and pushes them onto
131 /// the advice stack.
132 ///
133 /// If `include_len` is set to true, this also pushes the number of elements onto the advice
134 /// stack.
135 ///
136 /// Note: this operation doesn't consume the map element so it can be called multiple times
137 /// for the same key.
138 ///
139 /// # Example
140 /// Given an advice stack `[a, b, c, ...]`, and a map `x |-> [d, e, f]`:
141 ///
142 /// A call `push_stack(AdviceSource::Map { key: x, include_len: false })` will result in
143 /// advice stack: `[d, e, f, a, b, c, ...]`.
144 ///
145 /// A call `push_stack(AdviceSource::Map { key: x, include_len: true })` will result in
146 /// advice stack: `[3, d, e, f, a, b, c, ...]`.
147 ///
148 /// # Errors
149 /// Returns an error if the key was not found in the key-value map.
150 pub fn push_from_map(&mut self, key: Word, include_len: bool) -> Result<(), AdviceError> {
151 let values = self.map.get(&key).ok_or(AdviceError::MapKeyNotFound { key })?;
152
153 self.stack.extend(values.iter().rev());
154 if include_len {
155 self.stack
156 .push(Felt::try_from(values.len() as u64).expect("value length too big"));
157 }
158 Ok(())
159 }
160
161 /// Returns the current stack.
162 pub fn stack(&self) -> &[Felt] {
163 &self.stack
164 }
165
166 /// Extends the stack with the given elements.
167 ///
168 /// Elements are added to the top of the stack i.e. last element of this iterator is the first
169 /// element popped.
170 pub fn extend_stack<I>(&mut self, iter: I)
171 where
172 I: IntoIterator<Item = Felt>,
173 {
174 self.stack.extend(iter);
175 }
176
177 // ADVICE MAP
178 // --------------------------------------------------------------------------------------------
179
180 /// Returns true if the key has a corresponding value in the map.
181 pub fn contains_map_key(&self, key: &Word) -> bool {
182 self.map.contains_key(key)
183 }
184
185 /// Returns a reference to the value(s) associated with the specified key in the advice map.
186 pub fn get_mapped_values(&self, key: &Word) -> Option<&[Felt]> {
187 self.map.get(key).map(|value| value.as_ref())
188 }
189
190 /// Inserts the provided value into the advice map under the specified key.
191 ///
192 /// The values in the advice map can be moved onto the advice stack by invoking
193 /// the [AdviceProvider::push_from_map()] method.
194 ///
195 /// Returns an error if the specified key is already present in the advice map.
196 pub fn insert_into_map(&mut self, key: Word, values: Vec<Felt>) -> Result<(), AdviceError> {
197 match self.map.entry(key) {
198 Entry::Vacant(entry) => {
199 entry.insert(values.into());
200 },
201 Entry::Occupied(entry) => {
202 let existing_values = entry.get().as_ref();
203 if existing_values != values {
204 return Err(AdviceError::MapKeyAlreadyPresent {
205 key,
206 prev_values: existing_values.to_vec(),
207 new_values: values,
208 });
209 }
210 },
211 }
212 Ok(())
213 }
214
215 /// Merges all entries from the given [`AdviceMap`] into the current advice map.
216 ///
217 /// Returns an error if any new entry already exists with the same key but a different value
218 /// than the one currently stored. The current map remains unchanged.
219 pub fn extend_map(&mut self, other: &AdviceMap) -> Result<(), AdviceError> {
220 self.map.merge(other).map_err(|((key, prev_values), new_values)| {
221 AdviceError::MapKeyAlreadyPresent {
222 key,
223 prev_values: prev_values.to_vec(),
224 new_values: new_values.to_vec(),
225 }
226 })
227 }
228
229 // MERKLE STORE
230 // --------------------------------------------------------------------------------------------
231
232 /// Returns a node at the specified depth and index in a Merkle tree with the given root.
233 ///
234 /// # Errors
235 /// Returns an error if:
236 /// - A Merkle tree for the specified root cannot be found in this advice provider.
237 /// - The specified depth is either zero or greater than the depth of the Merkle tree identified
238 /// by the specified root.
239 /// - Value of the node at the specified depth and index is not known to this advice provider.
240 pub fn get_tree_node(
241 &self,
242 root: Word,
243 depth: &Felt,
244 index: &Felt,
245 ) -> Result<Word, AdviceError> {
246 let index = NodeIndex::from_elements(depth, index).map_err(|_| {
247 AdviceError::InvalidMerkleTreeNodeIndex { depth: *depth, index: *index }
248 })?;
249 self.store.get_node(root, index).map_err(AdviceError::MerkleStoreLookupFailed)
250 }
251
252 /// Returns a path to a node at the specified depth and index in a Merkle tree with the
253 /// specified root.
254 ///
255 /// # Errors
256 /// Returns an error if:
257 /// - A Merkle tree for the specified root cannot be found in this advice provider.
258 /// - The specified depth is either zero or greater than the depth of the Merkle tree identified
259 /// by the specified root.
260 /// - Path to the node at the specified depth and index is not known to this advice provider.
261 pub fn get_merkle_path(
262 &self,
263 root: Word,
264 depth: &Felt,
265 index: &Felt,
266 ) -> Result<MerklePath, AdviceError> {
267 let index = NodeIndex::from_elements(depth, index).map_err(|_| {
268 AdviceError::InvalidMerkleTreeNodeIndex { depth: *depth, index: *index }
269 })?;
270 self.store
271 .get_path(root, index)
272 .map(|value| value.path)
273 .map_err(AdviceError::MerkleStoreLookupFailed)
274 }
275
276 /// Updates a node at the specified depth and index in a Merkle tree with the specified root;
277 /// returns the Merkle path from the updated node to the new root, together with the new root.
278 ///
279 /// The tree is cloned prior to the update. Thus, the advice provider retains the original and
280 /// the updated tree.
281 ///
282 /// # Errors
283 /// Returns an error if:
284 /// - A Merkle tree for the specified root cannot be found in this advice provider.
285 /// - The specified depth is either zero or greater than the depth of the Merkle tree identified
286 /// by the specified root.
287 /// - Path to the leaf at the specified index in the specified Merkle tree is not known to this
288 /// advice provider.
289 pub fn update_merkle_node(
290 &mut self,
291 root: Word,
292 depth: &Felt,
293 index: &Felt,
294 value: Word,
295 ) -> Result<(MerklePath, Word), AdviceError> {
296 let node_index = NodeIndex::from_elements(depth, index).map_err(|_| {
297 AdviceError::InvalidMerkleTreeNodeIndex { depth: *depth, index: *index }
298 })?;
299 self.store
300 .set_node(root, node_index, value)
301 .map(|root| (root.path, root.root))
302 .map_err(AdviceError::MerkleStoreUpdateFailed)
303 }
304
305 /// Creates a new Merkle tree in the advice provider by combining Merkle trees with the
306 /// specified roots. The root of the new tree is defined as `hash(left_root, right_root)`.
307 ///
308 /// After the operation, both the original trees and the new tree remains in the advice
309 /// provider (i.e., the input trees are not removed).
310 ///
311 /// It is not checked whether a Merkle tree for either of the specified roots can be found in
312 /// this advice provider.
313 pub fn merge_roots(&mut self, lhs: Word, rhs: Word) -> Result<Word, AdviceError> {
314 self.store.merge_roots(lhs, rhs).map_err(AdviceError::MerkleStoreMergeFailed)
315 }
316
317 /// Returns true if the Merkle root exists for the advice provider Merkle store.
318 pub fn has_merkle_root(&self, root: Word) -> bool {
319 self.store.get_node(root, NodeIndex::root()).is_ok()
320 }
321
322 /// Extends the [MerkleStore] with the given nodes.
323 pub fn extend_merkle_store<I>(&mut self, iter: I)
324 where
325 I: IntoIterator<Item = InnerNodeInfo>,
326 {
327 self.store.extend(iter);
328 }
329
330 // MUTATORS
331 // --------------------------------------------------------------------------------------------
332
333 /// Extends the contents of this instance with the contents of an `AdviceInputs`.
334 pub fn extend_from_inputs(&mut self, inputs: &AdviceInputs) -> Result<(), AdviceError> {
335 self.extend_stack(inputs.stack.iter().cloned().rev());
336 self.extend_merkle_store(inputs.store.inner_nodes());
337 self.extend_map(&inputs.map)
338 }
339
340 /// Consumes `self` and return its parts (stack, map, store).
341 ///
342 /// Note that the order of the stack is such that the element at the top of the stack is at the
343 /// end of the returned vector.
344 pub fn into_parts(self) -> (Vec<Felt>, AdviceMap, MerkleStore) {
345 (self.stack, self.map, self.store)
346 }
347}
348
349impl From<AdviceInputs> for AdviceProvider {
350 fn from(inputs: AdviceInputs) -> Self {
351 let AdviceInputs { mut stack, map, store } = inputs;
352 stack.reverse();
353 Self { stack, map, store }
354 }
355}