Skip to main content

miden_protocol/account/code/
procedure.rs

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