miden_testing/
mock_host.rs1use alloc::{boxed::Box, collections::BTreeSet, rc::Rc, sync::Arc};
2
3use miden_lib::transaction::{TransactionEvent, TransactionEventError};
4use miden_objects::{
5 Digest,
6 account::{AccountHeader, AccountVaultDelta},
7 assembly::mast::MastNodeExt,
8};
9use miden_tx::{TransactionMastStore, host::AccountProcedureIndexMap};
10use vm_processor::{
11 AdviceInputs, AdviceProvider, AdviceSource, ContextId, ErrorContext, ExecutionError, Host,
12 MastForest, MastForestStore, MemAdviceProvider, ProcessState,
13};
14
15pub struct MockHost {
23 adv_provider: MemAdviceProvider,
24 acct_procedure_index_map: AccountProcedureIndexMap,
25 mast_store: Rc<TransactionMastStore>,
26}
27
28impl MockHost {
29 pub fn new(
31 account: AccountHeader,
32 advice_inputs: AdviceInputs,
33 mast_store: Rc<TransactionMastStore>,
34 mut foreign_code_commitments: BTreeSet<Digest>,
35 ) -> Self {
36 foreign_code_commitments.insert(account.code_commitment());
37 let adv_provider: MemAdviceProvider = advice_inputs.into();
38 let proc_index_map = AccountProcedureIndexMap::new(foreign_code_commitments, &adv_provider);
39
40 Self {
41 adv_provider,
42 acct_procedure_index_map: proc_index_map.unwrap(),
43 mast_store,
44 }
45 }
46
47 pub fn into_parts(self) -> (MemAdviceProvider, AccountVaultDelta) {
49 (self.adv_provider, AccountVaultDelta::default())
50 }
51
52 fn on_push_account_procedure_index(
56 &mut self,
57 process: ProcessState,
58 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
59 ) -> Result<(), ExecutionError> {
60 let proc_idx = self
61 .acct_procedure_index_map
62 .get_proc_index(&process)
63 .map_err(|err| ExecutionError::event_error(Box::new(err), err_ctx))?;
64 self.adv_provider.push_stack(AdviceSource::Value(proc_idx.into()), err_ctx)?;
65 Ok(())
66 }
67}
68
69impl Host for MockHost {
70 type AdviceProvider = MemAdviceProvider;
71
72 fn advice_provider(&self) -> &Self::AdviceProvider {
73 &self.adv_provider
74 }
75
76 fn advice_provider_mut(&mut self) -> &mut Self::AdviceProvider {
77 &mut self.adv_provider
78 }
79
80 fn get_mast_forest(&self, node_digest: &Digest) -> Option<Arc<MastForest>> {
81 self.mast_store.get(node_digest)
82 }
83
84 fn on_event(
85 &mut self,
86 process: ProcessState,
87 event_id: u32,
88 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
89 ) -> Result<(), ExecutionError> {
90 let event = TransactionEvent::try_from(event_id)
91 .map_err(|err| ExecutionError::event_error(Box::new(err), err_ctx))?;
92
93 if process.ctx() != ContextId::root() {
94 return Err(ExecutionError::event_error(
95 Box::new(TransactionEventError::NotRootContext(event_id)),
96 err_ctx,
97 ));
98 }
99
100 match event {
101 TransactionEvent::AccountPushProcedureIndex => {
102 self.on_push_account_procedure_index(process, err_ctx)
103 },
104 _ => Ok(()),
105 }?;
106
107 Ok(())
108 }
109}