miden_processor/host/advice/
mod.rs

1use alloc::vec::Vec;
2
3use vm_core::{
4    crypto::{hash::RpoDigest, merkle::MerklePath},
5    Felt,
6};
7
8use crate::{ExecutionError, ProcessState, Word};
9
10mod inputs;
11pub use inputs::AdviceInputs;
12
13mod providers;
14pub use providers::{MemAdviceProvider, RecAdviceProvider};
15
16mod source;
17pub use source::AdviceSource;
18
19// ADVICE PROVIDER
20// ================================================================================================
21
22/// Defines behavior of an advice provider.
23///
24/// An advice provider is a component through which the host can interact with the advice provider.
25/// The host can request nondeterministic inputs from the advice provider (i.e., result of a
26/// computation performed outside of the VM), as well as insert new data into the advice provider.
27///
28/// An advice provider consists of the following components:
29/// 1. Advice stack, which is a LIFO data structure. The processor can move the elements from the
30///    advice stack onto the operand stack, as well as push new elements onto the advice stack.
31/// 2. Advice map, which is a key-value map where keys are words (4 field elements) and values are
32///    vectors of field elements. The processor can push the values from the map onto the advice
33///    stack, as well as insert new values into the map.
34/// 3. Merkle store, which contains structured data reducible to Merkle paths. The VM can request
35///    Merkle paths from the store, as well as mutate it by updating or merging nodes contained in
36///    the store.
37pub trait AdviceProvider: Sized {
38    // REQUIRED METHODS
39    // --------------------------------------------------------------------------------------------
40
41    // ADVICE STACK
42    // --------------------------------------------------------------------------------------------
43
44    /// Pops an element from the advice stack and returns it.
45    ///
46    /// # Errors
47    /// Returns an error if the advice stack is empty.
48    fn pop_stack(&mut self, process: ProcessState) -> Result<Felt, ExecutionError>;
49
50    /// Pops a word (4 elements) from the advice stack and returns it.
51    ///
52    /// Note: a word is popped off the stack element-by-element. For example, a `[d, c, b, a, ...]`
53    /// stack (i.e., `d` is at the top of the stack) will yield `[d, c, b, a]`.
54    ///
55    /// # Errors
56    /// Returns an error if the advice stack does not contain a full word.
57    fn pop_stack_word(&mut self, process: ProcessState) -> Result<Word, ExecutionError>;
58
59    /// Pops a double word (8 elements) from the advice stack and returns them.
60    ///
61    /// Note: words are popped off the stack element-by-element. For example, a
62    /// `[h, g, f, e, d, c, b, a, ...]` stack (i.e., `h` is at the top of the stack) will yield
63    /// two words: `[h, g, f,e ], [d, c, b, a]`.
64    ///
65    /// # Errors
66    /// Returns an error if the advice stack does not contain two words.
67    fn pop_stack_dword(&mut self, process: ProcessState) -> Result<[Word; 2], ExecutionError>;
68
69    /// Pushes the value(s) specified by the source onto the advice stack.
70    ///
71    /// # Errors
72    /// Returns an error if the value specified by the advice source cannot be obtained.
73    fn push_stack(&mut self, source: AdviceSource) -> Result<(), ExecutionError>;
74
75    // ADVICE MAP
76    // --------------------------------------------------------------------------------------------
77
78    /// Returns a reference to the value(s) associated with the specified key in the advice map.
79    fn get_mapped_values(&self, key: &RpoDigest) -> Option<&[Felt]>;
80
81    /// Inserts the provided value into the advice map under the specified key.
82    ///
83    /// The values in the advice map can be moved onto the advice stack by invoking
84    /// [AdviceProvider::push_stack()] method.
85    ///
86    /// If the specified key is already present in the advice map, the values under the key
87    /// are replaced with the specified values.
88    fn insert_into_map(&mut self, key: Word, values: Vec<Felt>);
89
90    // MERKLE STORE
91    // --------------------------------------------------------------------------------------------
92
93    /// Returns a node at the specified depth and index in a Merkle tree with the given root.
94    ///
95    /// # Errors
96    /// Returns an error if:
97    /// - A Merkle tree for the specified root cannot be found in this advice provider.
98    /// - The specified depth is either zero or greater than the depth of the Merkle tree identified
99    ///   by the specified root.
100    /// - Value of the node at the specified depth and index is not known to this advice provider.
101    fn get_tree_node(&self, root: Word, depth: &Felt, index: &Felt)
102        -> Result<Word, ExecutionError>;
103
104    /// Returns a path to a node at the specified depth and index in a Merkle tree with the
105    /// specified root.
106    ///
107    /// # Errors
108    /// Returns an error if:
109    /// - A Merkle tree for the specified root cannot be found in this advice provider.
110    /// - The specified depth is either zero or greater than the depth of the Merkle tree identified
111    ///   by the specified root.
112    /// - Path to the node at the specified depth and index is not known to this advice provider.
113    fn get_merkle_path(
114        &self,
115        root: Word,
116        depth: &Felt,
117        index: &Felt,
118    ) -> Result<MerklePath, ExecutionError>;
119
120    /// Reconstructs a path from the root until a leaf or empty node and returns its depth.
121    ///
122    /// For more information, check [crate::crypto::MerkleStore::get_leaf_depth].
123    ///
124    /// # Errors
125    /// Will return an error if:
126    /// - The provided `tree_depth` doesn't fit `u8`.
127    /// - The conditions of [crate::crypto::MerkleStore::get_leaf_depth] aren't met.
128    fn get_leaf_depth(
129        &self,
130        root: Word,
131        tree_depth: &Felt,
132        index: &Felt,
133    ) -> Result<u8, ExecutionError>;
134
135    /// Updates a node at the specified depth and index in a Merkle tree with the specified root;
136    /// returns the Merkle path from the updated node to the new root, together with the new root.
137    ///
138    /// The tree is cloned prior to the update. Thus, the advice provider retains the original and
139    /// the updated tree.
140    ///
141    /// # Errors
142    /// Returns an error if:
143    /// - A Merkle tree for the specified root cannot be found in this advice provider.
144    /// - The specified depth is either zero or greater than the depth of the Merkle tree identified
145    ///   by the specified root.
146    /// - Path to the leaf at the specified index in the specified Merkle tree is not known to this
147    ///   advice provider.
148    fn update_merkle_node(
149        &mut self,
150        root: Word,
151        depth: &Felt,
152        index: &Felt,
153        value: Word,
154    ) -> Result<(MerklePath, Word), ExecutionError>;
155
156    /// Creates a new Merkle tree in the advice provider by combining Merkle trees with the
157    /// specified roots. The root of the new tree is defined as `hash(left_root, right_root)`.
158    ///
159    /// After the operation, both the original trees and the new tree remains in the advice
160    /// provider (i.e., the input trees are not removed).
161    ///
162    /// It is not checked whether a Merkle tree for either of the specified roots can be found in
163    /// this advice provider.
164    fn merge_roots(&mut self, lhs: Word, rhs: Word) -> Result<Word, ExecutionError>;
165}