Skip to main content

miden_protocol/account/component/
code.rs

1use miden_assembly::Library;
2use miden_processor::MastForest;
3
4use crate::vm::AdviceMap;
5
6// ACCOUNT COMPONENT CODE
7// ================================================================================================
8
9/// A [`Library`] that has been assembled for use as component code.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct AccountComponentCode(Library);
12
13impl AccountComponentCode {
14    /// Returns a reference to the underlying [`Library`]
15    pub fn as_library(&self) -> &Library {
16        &self.0
17    }
18
19    /// Returns a reference to the code's [`MastForest`]
20    pub fn mast_forest(&self) -> &MastForest {
21        self.0.mast_forest().as_ref()
22    }
23
24    /// Consumes `self` and returns the underlying [`Library`]
25    pub fn into_library(self) -> Library {
26        self.0
27    }
28
29    /// Returns a new [AccountComponentCode] with the provided advice map entries merged into the
30    /// underlying [Library]'s [MastForest].
31    ///
32    /// This allows adding advice map entries to an already-compiled account component,
33    /// which is useful when the entries are determined after compilation.
34    pub fn with_advice_map(self, advice_map: AdviceMap) -> Self {
35        if advice_map.is_empty() {
36            return self;
37        }
38
39        Self(self.0.with_advice_map(advice_map))
40    }
41}
42
43impl AsRef<Library> for AccountComponentCode {
44    fn as_ref(&self) -> &Library {
45        self.as_library()
46    }
47}
48
49// CONVERSIONS
50// ================================================================================================
51
52impl From<Library> for AccountComponentCode {
53    fn from(value: Library) -> Self {
54        Self(value)
55    }
56}
57
58impl From<AccountComponentCode> for Library {
59    fn from(value: AccountComponentCode) -> Self {
60        value.into_library()
61    }
62}
63
64// TESTS
65// ================================================================================================
66
67#[cfg(test)]
68mod tests {
69    use miden_core::{Felt, Word};
70
71    use super::*;
72    use crate::assembly::Assembler;
73
74    #[test]
75    fn test_account_component_code_with_advice_map() {
76        let assembler = Assembler::default();
77        let library = assembler
78            .assemble_library(["pub proc test nop end"])
79            .expect("failed to assemble library");
80        let component_code = AccountComponentCode::from(library);
81
82        assert!(component_code.mast_forest().advice_map().is_empty());
83
84        // Empty advice map should be a no-op (digest stays the same)
85        let cloned = component_code.clone();
86        let original_digest = cloned.as_library().digest();
87        let component_code = component_code.with_advice_map(AdviceMap::default());
88        assert_eq!(original_digest, component_code.as_library().digest());
89
90        // Non-empty advice map should add entries
91        let key = Word::from([10u32, 20, 30, 40]);
92        let value = vec![Felt::new(200)];
93        let mut advice_map = AdviceMap::default();
94        advice_map.insert(key, value.clone());
95
96        let component_code = component_code.with_advice_map(advice_map);
97
98        let mast = component_code.mast_forest();
99        let stored = mast.advice_map().get(&key).expect("entry should be present");
100        assert_eq!(stored.as_ref(), value.as_slice());
101    }
102}