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}