miden_tx/host/
account_procedures.rs1use miden_lib::transaction::memory::{ACCOUNT_STACK_TOP_PTR, ACCT_CODE_COMMITMENT_OFFSET};
2use miden_objects::account::AccountCode;
3
4use super::{BTreeMap, ProcessState, Word};
5use crate::errors::{TransactionHostError, TransactionKernelError};
6
7#[derive(Debug, Clone, Default)]
14pub struct AccountProcedureIndexMap(BTreeMap<Word, BTreeMap<Word, u8>>);
15
16impl AccountProcedureIndexMap {
17 pub fn new<'code>(
20 account_codes: impl IntoIterator<Item = &'code AccountCode>,
21 ) -> Result<Self, TransactionHostError> {
22 let mut index_map = Self::default();
23
24 for account_code in account_codes {
25 if !index_map.0.contains_key(&account_code.commitment()) {
27 index_map.insert_code(account_code)?;
28 }
29 }
30
31 Ok(index_map)
32 }
33
34 pub fn insert_code(&mut self, code: &AccountCode) -> Result<(), TransactionHostError> {
41 let mut procedure_map = BTreeMap::new();
42 for (proc_idx, proc_info) in code.procedures().iter().enumerate() {
43 let proc_idx = u8::try_from(proc_idx).map_err(|_| {
44 TransactionHostError::AccountProcedureIndexMapError(
45 "procedure index out of bounds".into(),
46 )
47 })?;
48
49 procedure_map.insert(*proc_info.mast_root(), proc_idx);
50 }
51
52 self.0.insert(code.commitment(), procedure_map);
53
54 Ok(())
55 }
56
57 pub fn get_proc_index(&self, process: &ProcessState) -> Result<u8, TransactionKernelError> {
64 let code_commitment = {
66 let account_stack_top_ptr = process
67 .get_mem_value(process.ctx(), ACCOUNT_STACK_TOP_PTR)
68 .expect("Account stack top pointer was not initialized")
69 .as_int();
70 let curr_data_ptr = process
71 .get_mem_value(
72 process.ctx(),
73 account_stack_top_ptr
74 .try_into()
75 .expect("account stack top pointer should be less than u32::MAX"),
76 )
77 .expect("active account pointer was not initialized")
78 .as_int();
79 process
80 .get_mem_word(process.ctx(), curr_data_ptr as u32 + ACCT_CODE_COMMITMENT_OFFSET)
81 .expect("failed to read a word from memory")
82 .expect("active account code commitment was not initialized")
83 };
84
85 let proc_root = process.get_stack_word_be(1);
86
87 self.0
88 .get(&code_commitment)
89 .ok_or(TransactionKernelError::UnknownCodeCommitment(code_commitment))?
90 .get(&proc_root)
91 .cloned()
92 .ok_or(TransactionKernelError::UnknownAccountProcedure(proc_root))
93 }
94}