miden_debug_engine/exec/
advice.rs1use std::sync::{Arc, Mutex};
5
6use miden_core::{
7 Felt, Word,
8 crypto::merkle::InnerNodeInfo,
9 serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
10};
11use miden_processor::advice::{AdviceMap, AdviceMutation, AdviceStack};
12
13pub fn clone_advice_mutation(mutation: &AdviceMutation) -> AdviceMutation {
18 match mutation {
19 AdviceMutation::ExtendStack { stack } => AdviceMutation::ExtendStack {
20 stack: stack.clone(),
21 },
22 AdviceMutation::ExtendMap { map: other } => {
23 AdviceMutation::ExtendMap { map: other.clone() }
24 }
25 AdviceMutation::ExtendMerkleStore { inner_nodes } => AdviceMutation::ExtendMerkleStore {
26 inner_nodes: inner_nodes.clone(),
27 },
28 }
29}
30
31pub fn clone_advice_mutations(mutations: &[AdviceMutation]) -> Vec<AdviceMutation> {
33 mutations.iter().map(clone_advice_mutation).collect()
34}
35
36const TAG_EXTEND_STACK: u8 = 0;
42const TAG_EXTEND_MAP: u8 = 1;
43const TAG_EXTEND_MERKLE_STORE: u8 = 2;
44
45pub fn write_advice_mutation<W: ByteWriter>(mutation: &AdviceMutation, target: &mut W) {
47 match mutation {
48 AdviceMutation::ExtendStack { stack } => {
49 target.write_u8(TAG_EXTEND_STACK);
50 stack.iter().copied().collect::<Vec<_>>().write_into(target);
51 }
52 AdviceMutation::ExtendMap { map } => {
53 target.write_u8(TAG_EXTEND_MAP);
54 map.write_into(target);
55 }
56 AdviceMutation::ExtendMerkleStore { inner_nodes } => {
57 target.write_u8(TAG_EXTEND_MERKLE_STORE);
58 target.write_usize(inner_nodes.len());
59 for info in inner_nodes {
60 info.value.write_into(target);
61 info.left.write_into(target);
62 info.right.write_into(target);
63 }
64 }
65 }
66}
67
68pub fn read_advice_mutation<R: ByteReader>(
70 source: &mut R,
71) -> Result<AdviceMutation, DeserializationError> {
72 match source.read_u8()? {
73 TAG_EXTEND_STACK => Ok(AdviceMutation::ExtendStack {
74 stack: AdviceStack::from(Vec::<Felt>::read_from(source)?),
75 }),
76 TAG_EXTEND_MAP => Ok(AdviceMutation::ExtendMap {
77 map: AdviceMap::read_from(source)?,
78 }),
79 TAG_EXTEND_MERKLE_STORE => {
80 let len = source.read_usize()?;
81 let mut inner_nodes = Vec::with_capacity(len);
82 for _ in 0..len {
83 let value = Word::read_from(source)?;
84 let left = Word::read_from(source)?;
85 let right = Word::read_from(source)?;
86 inner_nodes.push(InnerNodeInfo { value, left, right });
87 }
88 Ok(AdviceMutation::ExtendMerkleStore { inner_nodes })
89 }
90 other => Err(DeserializationError::InvalidValue(format!(
91 "unknown AdviceMutation variant tag: {other}"
92 ))),
93 }
94}
95
96pub fn write_event_log<W: ByteWriter>(log: &[Vec<AdviceMutation>], target: &mut W) {
101 target.write_usize(log.len());
102 for batch in log {
103 target.write_usize(batch.len());
104 for mutation in batch {
105 write_advice_mutation(mutation, target);
106 }
107 }
108}
109
110pub fn read_event_log<R: ByteReader>(
115 source: &mut R,
116) -> Result<Vec<Vec<AdviceMutation>>, DeserializationError> {
117 let batches = source.read_usize()?;
118 let mut log = Vec::with_capacity(batches);
119 for _ in 0..batches {
120 let len = source.read_usize()?;
121 let mut batch = Vec::with_capacity(len);
122 for _ in 0..len {
123 batch.push(read_advice_mutation(source)?);
124 }
125 log.push(batch);
126 }
127 Ok(log)
128}
129
130#[derive(Clone, Default)]
143pub struct EventMutationRecorder {
144 log: Arc<Mutex<Vec<Vec<AdviceMutation>>>>,
145}
146
147impl core::fmt::Debug for EventMutationRecorder {
148 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149 f.debug_struct("EventMutationRecorder").field("events", &self.len()).finish()
150 }
151}
152
153impl EventMutationRecorder {
154 pub fn new() -> Self {
156 Self::default()
157 }
158
159 pub fn take(&self) -> Vec<Vec<AdviceMutation>> {
161 core::mem::take(&mut *self.log.lock().expect("event mutation log poisoned"))
162 }
163
164 pub fn snapshot(&self) -> Vec<Vec<AdviceMutation>> {
166 self.log
167 .lock()
168 .expect("event mutation log poisoned")
169 .iter()
170 .map(|batch| clone_advice_mutations(batch))
171 .collect()
172 }
173
174 pub fn len(&self) -> usize {
176 self.log.lock().expect("event mutation log poisoned").len()
177 }
178
179 pub fn is_empty(&self) -> bool {
181 self.len() == 0
182 }
183
184 pub(crate) fn record(&self, mutations: Vec<AdviceMutation>) {
186 self.log.lock().expect("event mutation log poisoned").push(mutations);
187 }
188
189 pub(crate) fn clear(&self) {
191 self.log.lock().expect("event mutation log poisoned").clear();
192 }
193}