1use alloc::vec::Vec;
2
3use crate::{
4 Felt, Word,
5 crypto::merkle::MerkleStore,
6 serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
7};
8
9mod map;
10pub use map::AdviceMap;
11
12mod stack;
13pub use stack::AdviceStack;
14
15#[derive(Clone, Debug, Default, PartialEq, Eq)]
30pub struct AdviceInputs {
31 stack: AdviceStack,
32 map: AdviceMap,
33 store: MerkleStore,
34}
35
36impl AdviceInputs {
37 pub fn new(stack: AdviceStack, map: AdviceMap, store: MerkleStore) -> Self {
42 Self { stack, map, store }
43 }
44
45 pub fn with_stack(mut self, stack: AdviceStack) -> Self {
47 self.stack = stack;
48 self
49 }
50
51 pub fn stack(&self) -> AdviceStack {
53 self.stack.clone()
54 }
55
56 pub fn map(&self) -> &AdviceMap {
58 &self.map
59 }
60
61 pub fn store(&self) -> &MerkleStore {
63 &self.store
64 }
65
66 pub fn with_map<I>(mut self, iter: I) -> Self
68 where
69 I: IntoIterator<Item = (Word, Vec<Felt>)>,
70 {
71 self.map.extend(iter);
72 self
73 }
74
75 pub fn with_merkle_store(mut self, store: MerkleStore) -> Self {
77 self.store = store;
78 self
79 }
80
81 pub fn extend(&mut self, other: Self) {
86 self.stack.append_elements(other.stack.into_elements());
87 self.map.extend(other.map);
88 self.store.extend(other.store.inner_nodes());
89 }
90
91 pub fn into_parts(self) -> (AdviceStack, AdviceMap, MerkleStore) {
93 (self.stack, self.map, self.store)
94 }
95}
96
97impl From<AdviceMap> for AdviceInputs {
98 fn from(map: AdviceMap) -> Self {
99 Self {
100 stack: AdviceStack::default(),
101 map,
102 store: MerkleStore::default(),
103 }
104 }
105}
106
107impl Serializable for AdviceInputs {
108 fn write_into<W: ByteWriter>(&self, target: &mut W) {
109 let Self { stack, map, store } = self;
110 let stack: Vec<Felt> = stack.iter().copied().collect();
111 stack.write_into(target);
112 map.write_into(target);
113 store.write_into(target);
114 }
115}
116
117impl Deserializable for AdviceInputs {
118 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
119 let stack = Vec::<Felt>::read_from(source)?;
120 let map = AdviceMap::read_from(source)?;
121 let store = MerkleStore::read_from(source)?;
122 Ok(Self { stack: stack.into(), map, store })
123 }
124}
125
126#[cfg(test)]
130mod tests {
131 use alloc::vec::Vec;
132
133 use super::{AdviceInputs, AdviceMap, AdviceStack};
134 use crate::{
135 Felt, Word,
136 crypto::merkle::MerkleStore,
137 serde::{Deserializable, Serializable},
138 };
139
140 #[test]
141 fn test_advice_inputs_eq() {
142 let advice1 = AdviceInputs::default();
143 let advice2 = AdviceInputs::default();
144
145 assert_eq!(advice1, advice2);
146
147 let advice1 =
148 AdviceInputs::default().with_stack(AdviceStack::try_from_values([1, 2, 3]).unwrap());
149 let advice2 =
150 AdviceInputs::default().with_stack(AdviceStack::try_from_values([1, 2, 3]).unwrap());
151
152 assert_eq!(advice1, advice2);
153 }
154
155 #[test]
156 fn test_advice_inputs_serialization() {
157 let advice1 =
158 AdviceInputs::default().with_stack(AdviceStack::try_from_values([1, 2, 3]).unwrap());
159 let bytes = advice1.to_bytes();
160 let advice2 = AdviceInputs::read_from_bytes(&bytes).unwrap();
161
162 assert_eq!(advice1, advice2);
163 }
164
165 #[test]
166 fn advice_inputs_new_assembles_parts() {
167 let stack = AdviceStack::try_from_values([1, 2, 3]).unwrap();
168 let map = AdviceMap::from_iter([(Word::default(), vec![Felt::new_unchecked(7)])]);
169 let store = MerkleStore::default();
170
171 let advice = AdviceInputs::new(stack.clone(), map.clone(), store.clone());
172
173 assert_eq!(advice.stack(), stack);
174 assert_eq!(advice.map, map);
175 assert_eq!(advice.store, store);
176 }
177
178 #[test]
179 fn advice_inputs_from_advice_map_defaults_other_parts() {
180 let map = AdviceMap::from_iter([(Word::default(), vec![Felt::new_unchecked(7)])]);
181
182 let advice = AdviceInputs::from(map.clone());
183
184 assert_eq!(advice.stack(), AdviceStack::default());
185 assert_eq!(advice.map, map);
186 assert_eq!(advice.store, MerkleStore::default());
187 }
188
189 #[test]
190 fn advice_inputs_accept_typed_advice_stack() {
191 let mut stack = AdviceStack::new();
192 stack.append_element(Felt::new_unchecked(1));
193 stack.append_word(
194 [
195 Felt::new_unchecked(2),
196 Felt::new_unchecked(3),
197 Felt::new_unchecked(4),
198 Felt::new_unchecked(5),
199 ]
200 .into(),
201 );
202
203 let advice = AdviceInputs::default().with_stack(stack.clone());
204
205 assert_eq!(advice.stack(), stack);
206 }
207
208 #[test]
209 fn advice_stack_consumes_word_sized_groups_top_first() {
210 let word0: Word = [
211 Felt::new_unchecked(1),
212 Felt::new_unchecked(2),
213 Felt::new_unchecked(3),
214 Felt::new_unchecked(4),
215 ]
216 .into();
217 let word1: Word = [
218 Felt::new_unchecked(5),
219 Felt::new_unchecked(6),
220 Felt::new_unchecked(7),
221 Felt::new_unchecked(8),
222 ]
223 .into();
224 let mut stack = AdviceStack::new();
225
226 stack.append_element(Felt::new_unchecked(0));
227 stack.append_word(word0);
228 stack.append_dword([word1, word0]);
229
230 assert_eq!(stack.consume_element(), Some(Felt::new_unchecked(0)));
231 assert_eq!(stack.consume_word(), Some(word0));
232 assert_eq!(stack.consume_dword(), Some([word1, word0]));
233 assert!(stack.is_empty());
234 }
235
236 #[test]
237 fn advice_stack_rejects_partial_dword_without_consuming() {
238 let word: Word = [
239 Felt::new_unchecked(1),
240 Felt::new_unchecked(2),
241 Felt::new_unchecked(3),
242 Felt::new_unchecked(4),
243 ]
244 .into();
245 let mut stack = AdviceStack::new();
246 stack.append_word(word);
247
248 assert_eq!(stack.consume_dword(), None);
249 assert_eq!(stack.consume_word(), Some(word));
250 }
251
252 #[test]
253 fn advice_stack_append_for_adv_push_matches_repeated_consumption() {
254 let values = [Felt::new_unchecked(1), Felt::new_unchecked(2), Felt::new_unchecked(3)];
255 let mut stack = AdviceStack::new();
256 stack.append_for_adv_push(&values);
257
258 assert_eq!(stack.consume_element(), Some(Felt::new_unchecked(3)));
259 assert_eq!(stack.consume_element(), Some(Felt::new_unchecked(2)));
260 assert_eq!(stack.consume_element(), Some(Felt::new_unchecked(1)));
261 assert!(stack.is_empty());
262 }
263
264 #[test]
265 fn advice_stack_append_for_adv_pipe_requires_dword_alignment() {
266 let values: Vec<Felt> = (1..=16).map(Felt::new_unchecked).collect();
267 let mut stack = AdviceStack::new();
268 stack.append_for_adv_pipe(&values);
269
270 assert_eq!(stack.into_elements(), values);
271 }
272
273 #[test]
274 #[should_panic(expected = "append_for_adv_pipe requires slice length to be a multiple of 8")]
275 fn advice_stack_append_for_adv_pipe_panics_on_misalignment() {
276 let values: Vec<Felt> = (1..=7).map(Felt::new_unchecked).collect();
277 let mut stack = AdviceStack::new();
278 stack.append_for_adv_pipe(&values);
279 }
280
281 #[test]
282 fn advice_stack_prepends_new_top_elements() {
283 let mut stack = AdviceStack::from(vec![Felt::new_unchecked(3), Felt::new_unchecked(4)]);
284
285 stack.push_element(Felt::new_unchecked(2));
286 stack.prepend_elements([Felt::new_unchecked(0), Felt::new_unchecked(1)]);
287
288 assert_eq!(
289 stack.into_elements(),
290 vec![
291 Felt::new_unchecked(0),
292 Felt::new_unchecked(1),
293 Felt::new_unchecked(2),
294 Felt::new_unchecked(3),
295 Felt::new_unchecked(4),
296 ]
297 );
298 }
299
300 #[test]
304 fn advice_stack_try_from_values_keeps_top_first_order() {
305 let stack = AdviceStack::try_from_values([1, 2, 3, 4]).unwrap();
306
307 assert_eq!(
308 stack.into_elements(),
309 vec![
310 Felt::new_unchecked(1),
311 Felt::new_unchecked(2),
312 Felt::new_unchecked(3),
313 Felt::new_unchecked(4)
314 ]
315 );
316 }
317}