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