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}