miden_processor/host/advice/
mod.rs

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