use crate::cairo_runner::dry_run::DryRunResult;
use crate::cairo_runner::{cairo_dry_run, input::dry_run::DryRunnerProgramInput};
use crate::constant::DRY_CAIRO_RUN_OUTPUT_FILE;
use crate::primitives::processed_types::cairo_format;
use crate::primitives::task::ExtendedModule;
use crate::provider::key::categorize_fetch_keys;
use crate::provider::traits::new_provider_from_config;
use core::panic;
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
use tracing::info;
use super::config::CompilerConfig;
use super::{Compilable, CompilationResult, CompileError};
pub type ModuleVec = Vec<ExtendedModule>;
impl Compilable for ModuleVec {
async fn compile(
&self,
compile_config: &CompilerConfig,
) -> Result<CompilationResult, CompileError> {
info!("target task: {:#?}", self[0].task);
let dry_run_program_path = compile_config.dry_run_program_path.clone();
let dry_run_input =
generate_input(self.to_vec(), PathBuf::from(DRY_CAIRO_RUN_OUTPUT_FILE)).await?;
let input_string =
serde_json::to_string_pretty(&dry_run_input).expect("Failed to serialize module class");
info!("2. Running dry-run... ");
let dry_run_results: DryRunResult = cairo_dry_run(
dry_run_program_path,
input_string,
compile_config.save_fetch_keys_file.clone(),
)?;
if dry_run_results[0].program_hash != self[0].task.program_hash {
return Err(CompileError::ClassHashMismatch);
}
if dry_run_results.len() != 1 {
panic!("Multiple Modules are not supported");
}
let dry_run_module = dry_run_results.into_iter().next().unwrap();
let commit_results = vec![dry_run_module.result.into()];
let categorized_keys = categorize_fetch_keys(dry_run_module.fetch_keys);
let mut accounts_map = HashMap::new();
let mut storages_map = HashMap::new();
let mut transactions_map = HashMap::new();
let mut transaction_receipts_map = HashMap::new();
let mut mmr_header_map = HashMap::new();
info!("3. Fetching proofs from provider...");
for (chain_id, keys) in categorized_keys {
info!("target provider chain id: {}", chain_id);
let target_provider_config = compile_config
.provider_config
.get(&chain_id)
.expect("target task's chain had not been configured.");
let provider = new_provider_from_config(target_provider_config);
let results = provider
.fetch_proofs_from_keys(keys)
.await?
.get_evm_proofs()
.unwrap();
mmr_header_map.insert(
chain_id.to_numeric_id(),
HashSet::from_iter(results.mmr_with_headers.into_iter()),
);
accounts_map.insert(
chain_id.to_numeric_id(),
HashSet::from_iter(results.accounts.into_iter()),
);
storages_map.insert(
chain_id.to_numeric_id(),
HashSet::from_iter(results.storages.into_iter()),
);
transactions_map.insert(
chain_id.to_numeric_id(),
HashSet::from_iter(results.transactions.into_iter()),
);
transaction_receipts_map.insert(
chain_id.to_numeric_id(),
HashSet::from_iter(results.transaction_receipts.into_iter()),
);
}
let compiled_result = CompilationResult::new(
commit_results,
mmr_header_map,
accounts_map,
storages_map,
transactions_map,
transaction_receipts_map,
);
Ok(compiled_result)
}
}
async fn generate_input(
extended_modules: Vec<ExtendedModule>,
identified_keys_file: PathBuf,
) -> Result<DryRunnerProgramInput, CompileError> {
let mut collected_results = Vec::new();
for module in extended_modules {
let input_module =
cairo_format::DryRunProcessedModule::new(module.task.inputs, module.module_class);
collected_results.push(input_module);
}
Ok(DryRunnerProgramInput::new(
identified_keys_file,
collected_results,
))
}