miden_testing/
executor.rs1#[cfg(test)]
2use miden_processor::DefaultHost;
3use miden_processor::fast::{ExecutionOutput, FastProcessor};
4use miden_processor::{AdviceInputs, AsyncHost, Program, StackInputs};
5#[cfg(test)]
6use miden_protocol::assembly::Assembler;
7
8use crate::ExecError;
9
10pub(crate) struct CodeExecutor<H> {
15 host: H,
16 stack_inputs: Option<StackInputs>,
17 advice_inputs: AdviceInputs,
18}
19
20impl<H: AsyncHost> CodeExecutor<H> {
21 pub(crate) fn new(host: H) -> Self {
24 Self {
25 host,
26 stack_inputs: None,
27 advice_inputs: AdviceInputs::default(),
28 }
29 }
30
31 pub fn extend_advice_inputs(mut self, advice_inputs: AdviceInputs) -> Self {
32 self.advice_inputs.extend(advice_inputs);
33 self
34 }
35
36 pub fn stack_inputs(mut self, stack_inputs: StackInputs) -> Self {
37 self.stack_inputs = Some(stack_inputs);
38 self
39 }
40
41 #[cfg(test)]
43 pub async fn run(self, code: &str) -> Result<ExecutionOutput, ExecError> {
44 use alloc::borrow::ToOwned;
45 use alloc::sync::Arc;
46
47 use miden_protocol::assembly::debuginfo::{SourceLanguage, Uri};
48 use miden_protocol::assembly::{DefaultSourceManager, SourceManagerSync};
49 use miden_standards::code_builder::CodeBuilder;
50
51 let source_manager: Arc<dyn SourceManagerSync> = Arc::new(DefaultSourceManager::default());
52 let assembler: Assembler = CodeBuilder::with_kernel_library(source_manager.clone()).into();
53
54 let virtual_source_file =
56 source_manager.load(SourceLanguage::Masm, Uri::new("_user_code"), code.to_owned());
57 let program = assembler.assemble_program(virtual_source_file).unwrap();
58
59 self.execute_program(program).await
60 }
61
62 pub async fn execute_program(mut self, program: Program) -> Result<ExecutionOutput, ExecError> {
67 let stack_inputs =
73 StackInputs::new(self.stack_inputs.unwrap_or_default().iter().copied().collect())
74 .unwrap();
75
76 let processor = FastProcessor::new_debug(stack_inputs.as_slice(), self.advice_inputs);
77
78 let execution_output =
79 processor.execute(&program, &mut self.host).await.map_err(ExecError::new)?;
80
81 Ok(execution_output)
82 }
83}
84
85#[cfg(test)]
86impl CodeExecutor<DefaultHost> {
87 pub fn with_default_host() -> Self {
88 use miden_core_lib::CoreLibrary;
89 use miden_protocol::ProtocolLib;
90 use miden_protocol::transaction::TransactionKernel;
91 use miden_standards::StandardsLib;
92
93 let mut host = DefaultHost::default();
94
95 let core_lib = CoreLibrary::default();
96 host.load_library(core_lib.mast_forest()).unwrap();
97
98 let standards_lib = StandardsLib::default();
99 host.load_library(standards_lib.mast_forest()).unwrap();
100
101 let protocol_lib = ProtocolLib::default();
102 host.load_library(protocol_lib.mast_forest()).unwrap();
103
104 let kernel_lib = TransactionKernel::library();
105 host.load_library(kernel_lib.mast_forest()).unwrap();
106
107 CodeExecutor::new(host)
108 }
109}