miden_core/operations/decorators/
mod.rs

1use alloc::{string::ToString, vec::Vec};
2use core::fmt;
3
4use miden_crypto::hash::blake::Blake3_256;
5use num_traits::ToBytes;
6
7mod assembly_op;
8pub use assembly_op::AssemblyOp;
9
10mod debug;
11pub use debug::DebugOptions;
12
13use crate::mast::{DecoratorFingerprint, DecoratorId};
14
15// DECORATORS
16// ================================================================================================
17
18/// A set of decorators which can be executed by the VM.
19///
20/// Executing a decorator does not affect the state of the main VM components such as operand stack
21/// and memory.
22///
23/// Executing decorators does not advance the VM clock. As such, many decorators can be executed in
24/// a single VM cycle.
25#[derive(Clone, Debug, Eq, PartialEq)]
26pub enum Decorator {
27    /// Adds information about the assembly instruction at a particular index (only applicable in
28    /// debug mode).
29    AsmOp(AssemblyOp),
30    /// Prints out information about the state of the VM based on the specified options. This
31    /// decorator is executed only in debug mode.
32    Debug(DebugOptions),
33    /// Emits a trace to the host.
34    Trace(u32),
35}
36
37impl Decorator {
38    pub fn fingerprint(&self) -> DecoratorFingerprint {
39        match self {
40            Self::AsmOp(asm_op) => {
41                let mut bytes_to_hash = Vec::new();
42                if let Some(location) = asm_op.location() {
43                    bytes_to_hash.extend(location.path.as_bytes());
44                    bytes_to_hash.extend(location.start.to_u32().to_le_bytes());
45                    bytes_to_hash.extend(location.end.to_u32().to_le_bytes());
46                }
47                bytes_to_hash.extend(asm_op.context_name().as_bytes());
48                bytes_to_hash.extend(asm_op.op().as_bytes());
49                bytes_to_hash.push(asm_op.num_cycles());
50                bytes_to_hash.push(asm_op.should_break() as u8);
51
52                Blake3_256::hash(&bytes_to_hash)
53            },
54            Self::Debug(debug) => Blake3_256::hash(debug.to_string().as_bytes()),
55            Self::Trace(trace) => Blake3_256::hash(&trace.to_le_bytes()),
56        }
57    }
58}
59
60impl crate::prettier::PrettyPrint for Decorator {
61    fn render(&self) -> crate::prettier::Document {
62        crate::prettier::display(self)
63    }
64}
65
66impl fmt::Display for Decorator {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        match self {
69            Self::AsmOp(assembly_op) => {
70                write!(f, "asmOp({}, {})", assembly_op.op(), assembly_op.num_cycles())
71            },
72            Self::Debug(options) => write!(f, "debug({options})"),
73            Self::Trace(trace_id) => write!(f, "trace({trace_id})"),
74        }
75    }
76}
77
78/// Vector consisting of a tuple of operation index (within a span block) and decorator at that
79/// index.
80///
81/// Note: for `AssemblyOp` decorators, when an instruction compiles down to multiple operations,
82/// only the first operation is associated with the assembly op.
83pub type DecoratorList = Vec<(usize, DecoratorId)>;
84
85/// Iterator used to iterate through the decorator list of a span block
86/// while executing operation batches of a span block.
87pub struct DecoratorIterator<'a> {
88    decorators: &'a DecoratorList,
89    idx: usize,
90}
91
92impl<'a> DecoratorIterator<'a> {
93    /// Returns a new instance of decorator iterator instantiated with the provided decorator list.
94    pub fn new(decorators: &'a DecoratorList) -> Self {
95        Self { decorators, idx: 0 }
96    }
97
98    /// Returns the next decorator but only if its position matches the specified position,
99    /// otherwise, None is returned.
100    #[inline(always)]
101    pub fn next_filtered(&mut self, pos: usize) -> Option<&DecoratorId> {
102        if self.idx < self.decorators.len() && self.decorators[self.idx].0 == pos {
103            self.idx += 1;
104            Some(&self.decorators[self.idx - 1].1)
105        } else {
106            None
107        }
108    }
109}
110
111impl<'a> Iterator for DecoratorIterator<'a> {
112    type Item = &'a DecoratorId;
113
114    fn next(&mut self) -> Option<Self::Item> {
115        if self.idx < self.decorators.len() {
116            self.idx += 1;
117            Some(&self.decorators[self.idx - 1].1)
118        } else {
119            None
120        }
121    }
122}
123
124// TYPES AND INTERFACES
125// ================================================================================================
126
127// Collection of signature schemes supported
128#[derive(Clone, Copy, PartialEq, Eq, Debug)]
129pub enum SignatureKind {
130    RpoFalcon512,
131}
132
133impl fmt::Display for SignatureKind {
134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135        match self {
136            Self::RpoFalcon512 => write!(f, "rpo_falcon512"),
137        }
138    }
139}