miden_testing/
executor.rs1#[cfg(test)]
2use miden_processor::DefaultHost;
3use miden_processor::advice::AdviceInputs;
4use miden_processor::{ExecutionOutput, FastProcessor, Host, 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: Host> 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 = self.stack_inputs.unwrap_or_default();
68
69 let processor = FastProcessor::new(stack_inputs)
70 .with_advice(self.advice_inputs)
71 .with_debugging(true);
72
73 let execution_output =
74 processor.execute(&program, &mut self.host).await.map_err(ExecError::new)?;
75
76 Ok(execution_output)
77 }
78}
79
80#[cfg(test)]
81impl CodeExecutor<DefaultHost> {
82 pub fn with_default_host() -> Self {
83 use miden_core_lib::CoreLibrary;
84 use miden_protocol::ProtocolLib;
85 use miden_protocol::transaction::TransactionKernel;
86 use miden_standards::StandardsLib;
87
88 let mut host = DefaultHost::default();
89
90 let core_lib = CoreLibrary::default();
91 host.load_library(core_lib.mast_forest()).unwrap();
92
93 let standards_lib = StandardsLib::default();
94 host.load_library(standards_lib.mast_forest()).unwrap();
95
96 let protocol_lib = ProtocolLib::default();
97 host.load_library(protocol_lib.mast_forest()).unwrap();
98
99 let kernel_lib = TransactionKernel::library();
100 host.load_library(kernel_lib.mast_forest()).unwrap();
101
102 CodeExecutor::new(host)
103 }
104}