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