Skip to main content

multiversx_sc_scenario/executor/
composite.rs

1use multiversx_chain_vm_executor::{
2    CompilationOptions, Executor, ExecutorError, Instance, MissingWasmError,
3};
4use simple_error::SimpleError;
5use std::fmt;
6
7use crate::executor::debug::ContractDebugExecutorNotRegisteredError;
8
9/// An executor that delegates instance creation to several other executors.
10///
11/// The executors are tried one after the other. If they return known whitelisted errors, we fall back to the next executor on the list.
12pub struct CompositeExecutor {
13    executors: Vec<Box<dyn Executor + Send + Sync>>,
14}
15
16impl fmt::Debug for CompositeExecutor {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        f.debug_struct("CompositeExecutor").finish()
19    }
20}
21
22impl CompositeExecutor {
23    pub fn new(executors: Vec<Box<dyn Executor + Send + Sync>>) -> Self {
24        CompositeExecutor { executors }
25    }
26}
27
28impl Executor for CompositeExecutor {
29    fn new_instance(
30        &self,
31        wasm_bytes: &[u8],
32        compilation_options: &CompilationOptions,
33    ) -> Result<Box<dyn Instance>, ExecutorError> {
34        for executor in &self.executors {
35            match executor.new_instance(wasm_bytes, compilation_options) {
36                Ok(instance) => {
37                    return Ok(instance);
38                }
39                Err(err) => {
40                    if !is_recoverable_error(&err) {
41                        return Err(err);
42                    }
43                }
44            }
45        }
46
47        Err(Box::new(SimpleError::new("contract not found")))
48    }
49
50    fn new_instance_from_cache(
51        &self,
52        _cache_bytes: &[u8],
53        _compilation_options: &CompilationOptions,
54    ) -> Result<Box<dyn Instance>, ExecutorError> {
55        panic!("DebugSCExecutor new_instance_from_cache not supported")
56    }
57}
58
59fn is_recoverable_error(err: &ExecutorError) -> bool {
60    if err.is::<ContractDebugExecutorNotRegisteredError>() {
61        return true;
62    }
63    if err.is::<MissingWasmError>() {
64        return true;
65    }
66    false
67}