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
80pub type DecoratorList = Vec<(usize, DecoratorId)>;
81
82/// Iterator used to iterate through the decorator list of a span block
83/// while executing operation batches of a span block.
84pub struct DecoratorIterator<'a> {
85    decorators: &'a DecoratorList,
86    idx: usize,
87}
88
89impl<'a> DecoratorIterator<'a> {
90    /// Returns a new instance of decorator iterator instantiated with the provided decorator list.
91    pub fn new(decorators: &'a DecoratorList) -> Self {
92        Self { decorators, idx: 0 }
93    }
94
95    /// Returns the next decorator but only if its position matches the specified position,
96    /// otherwise, None is returned.
97    #[inline(always)]
98    pub fn next_filtered(&mut self, pos: usize) -> Option<&DecoratorId> {
99        if self.idx < self.decorators.len() && self.decorators[self.idx].0 == pos {
100            self.idx += 1;
101            Some(&self.decorators[self.idx - 1].1)
102        } else {
103            None
104        }
105    }
106}
107
108impl<'a> Iterator for DecoratorIterator<'a> {
109    type Item = &'a DecoratorId;
110
111    fn next(&mut self) -> Option<Self::Item> {
112        if self.idx < self.decorators.len() {
113            self.idx += 1;
114            Some(&self.decorators[self.idx - 1].1)
115        } else {
116            None
117        }
118    }
119}
120
121// TYPES AND INTERFACES
122// ================================================================================================
123
124// Collection of signature schemes supported
125#[derive(Clone, Copy, PartialEq, Eq, Debug)]
126pub enum SignatureKind {
127    RpoFalcon512,
128}
129
130impl fmt::Display for SignatureKind {
131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132        match self {
133            Self::RpoFalcon512 => write!(f, "rpo_falcon512"),
134        }
135    }
136}