Skip to main content

miden_protocol/account/code/
procedure.rs

1use alloc::string::String;
2use alloc::sync::Arc;
3
4use miden_core::mast::MastForest;
5use miden_core::prettier::PrettyPrint;
6use miden_crypto_derive::WordWrapper;
7use miden_processor::mast::{MastNode, MastNodeExt, MastNodeId};
8
9use crate::Word;
10use crate::utils::serde::{
11    ByteReader,
12    ByteWriter,
13    Deserializable,
14    DeserializationError,
15    Serializable,
16};
17
18// ACCOUNT PROCEDURE ROOT
19// ================================================================================================
20
21/// The MAST root of a public procedure in an account's interface.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, WordWrapper)]
23pub struct AccountProcedureRoot(Word);
24
25impl AccountProcedureRoot {
26    /// The number of field elements that represent an [`AccountProcedureRoot`] in kernel memory.
27    pub const NUM_ELEMENTS: usize = 4;
28
29    // PUBLIC ACCESSORS
30    // --------------------------------------------------------------------------------------------
31
32    /// Returns a reference to the procedure's mast root.
33    pub fn mast_root(&self) -> &Word {
34        &self.0
35    }
36}
37
38impl core::fmt::Display for AccountProcedureRoot {
39    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
40        f.write_fmt(format_args!("{}", self.as_word()))
41    }
42}
43
44impl From<AccountProcedureRoot> for Word {
45    fn from(root: AccountProcedureRoot) -> Self {
46        *root.mast_root()
47    }
48}
49
50impl Serializable for AccountProcedureRoot {
51    fn write_into<W: ByteWriter>(&self, target: &mut W) {
52        target.write(self.0);
53    }
54
55    fn get_size_hint(&self) -> usize {
56        self.0.get_size_hint()
57    }
58}
59
60impl Deserializable for AccountProcedureRoot {
61    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
62        let mast_root: Word = source.read()?;
63        Ok(Self::from_raw(mast_root))
64    }
65}
66
67// PRINTABLE PROCEDURE
68// ================================================================================================
69
70/// A printable representation of a single account procedure.
71#[derive(Debug, Clone)]
72pub struct PrintableProcedure {
73    mast: Arc<MastForest>,
74    procedure_root: AccountProcedureRoot,
75    entrypoint: MastNodeId,
76}
77
78impl PrintableProcedure {
79    /// Creates a new PrintableProcedure instance from its components.
80    pub(crate) fn new(
81        mast: Arc<MastForest>,
82        procedure_root: AccountProcedureRoot,
83        entrypoint: MastNodeId,
84    ) -> Self {
85        Self { mast, procedure_root, entrypoint }
86    }
87
88    fn entrypoint(&self) -> &MastNode {
89        &self.mast[self.entrypoint]
90    }
91
92    pub(crate) fn mast_root(&self) -> &Word {
93        self.procedure_root.mast_root()
94    }
95}
96
97impl PrettyPrint for PrintableProcedure {
98    fn render(&self) -> miden_core::prettier::Document {
99        use miden_core::prettier::*;
100
101        indent(
102            4,
103            const_text("begin") + nl() + self.entrypoint().to_pretty_print(&self.mast).render(),
104        ) + nl()
105            + const_text("end")
106    }
107}
108
109// TESTS
110// ================================================================================================
111
112#[cfg(test)]
113mod tests {
114
115    use miden_crypto::utils::{Deserializable, Serializable};
116
117    use crate::account::{AccountCode, AccountProcedureRoot};
118
119    #[test]
120    fn test_serde_account_procedure() {
121        let account_code = AccountCode::mock();
122
123        let serialized = account_code.procedures()[0].to_bytes();
124        let deserialized = AccountProcedureRoot::read_from_bytes(&serialized).unwrap();
125
126        assert_eq!(account_code.procedures()[0], deserialized);
127    }
128}