diff --git a/crates/compiler/src/lib.rs b/crates/compiler/src/lib.rs index eb45c9f..15b3acc 100644 --- a/crates/compiler/src/lib.rs +++ b/crates/compiler/src/lib.rs @@ -14,8 +14,8 @@ use std::{ use alloy::json_abi::JsonAbi; use alloy_primitives::Address; -use semver::VersionReq; use anyhow::Context; +use semver::{Version, VersionReq}; use serde::{Deserialize, Serialize}; use revive_common::EVMVersion; @@ -63,13 +63,24 @@ pub struct CompilerInput { } /// The generic compilation output configuration. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct CompilerOutput { + /// Information about the `solc` compiler used to compile the contracts. + pub solc: SolcCompilerInformation, /// The compiled contracts. The bytecode of the contract is kept as a string incase linking is /// required and the compiled source has placeholders. pub contracts: HashMap>, } +/// Information about the `solc` compiler. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SolcCompilerInformation { + /// Version of the compiler. + pub version: Version, + /// Path to the compiler executable. + pub path: PathBuf, +} + /// A generic builder style interface for configuring the supported compiler options. pub struct Compiler { input: CompilerInput, diff --git a/crates/compiler/src/revive_resolc.rs b/crates/compiler/src/revive_resolc.rs index 6f78d02..d583fa2 100644 --- a/crates/compiler/src/revive_resolc.rs +++ b/crates/compiler/src/revive_resolc.rs @@ -1,7 +1,7 @@ //! Implements the [SolidityCompiler] trait with `resolc` for //! compiling contracts to PolkaVM (PVM) bytecode. -use std::{path::PathBuf, process::Stdio}; +use std::{collections::HashMap, path::PathBuf, process::Stdio}; use revive_dt_common::types::VersionOrRequirement; use revive_dt_config::Arguments; @@ -13,7 +13,10 @@ use revive_solc_json_interface::{ use super::constants::SOLC_VERSION_SUPPORTING_VIA_YUL_IR; use super::utils; -use crate::{CompilerInput, CompilerOutput, ModeOptimizerSetting, ModePipeline, SolidityCompiler}; +use crate::{ + CompilerInput, CompilerOutput, ModeOptimizerSetting, ModePipeline, SolcCompilerInformation, + SolidityCompiler, +}; use alloy::json_abi::JsonAbi; use anyhow::Context; @@ -23,10 +26,8 @@ use tokio::{io::AsyncWriteExt, process::Command as AsyncCommand}; /// A wrapper around the `resolc` binary, emitting PVM-compatible bytecode. #[derive(Debug)] pub struct Resolc { - // Enable wasm compilation. - wasm: bool, - // Where to cache artifacts. - cache_directory: PathBuf, + // Where to cache compiler executables. + compiler_executables_cache_directory: PathBuf, // We'll use this version when no explicit version // requirement is given in the test mode. solc_version: Version, @@ -64,9 +65,9 @@ impl SolidityCompiler for Resolc { let solc_version_req = solc_version .unwrap_or_else(|| VersionOrRequirement::version_to_requirement(&self.solc_version)); let solc_path = revive_dt_solc_binaries::download_solc( - &self.cache_directory, + &self.compiler_executables_cache_directory, solc_version_req, - self.wasm, + false, ) .await?; let solc_version = utils::solc_version(&solc_path).await?; @@ -202,14 +203,14 @@ impl SolidityCompiler for Resolc { anyhow::bail!("Unexpected error - resolc output doesn't have a contracts section"); }; - let mut compiler_output = CompilerOutput::default(); + let mut compiled_contracts = HashMap::>::new(); for (source_path, contracts) in contracts.into_iter() { let src_for_msg = source_path.clone(); let source_path = PathBuf::from(source_path) .canonicalize() .with_context(|| format!("Failed to canonicalize path {src_for_msg}"))?; - let map = compiler_output.contracts.entry(source_path).or_default(); + let map = compiled_contracts.entry(source_path).or_default(); for (contract_name, contract_information) in contracts.into_iter() { let bytecode = contract_information .evm @@ -254,13 +255,18 @@ impl SolidityCompiler for Resolc { } } - Ok(compiler_output) + Ok(CompilerOutput { + solc: SolcCompilerInformation { + version: solc_version, + path: solc_path, + }, + contracts: compiled_contracts, + }) } fn new(config: &Arguments) -> Self { Resolc { - wasm: config.wasm, - cache_directory: config.directory().to_path_buf(), + compiler_executables_cache_directory: config.directory().to_path_buf(), solc_version: config.solc.clone(), resolc_path: config.resolc.clone(), } diff --git a/crates/compiler/src/solc.rs b/crates/compiler/src/solc.rs index b5ac044..211e4e4 100644 --- a/crates/compiler/src/solc.rs +++ b/crates/compiler/src/solc.rs @@ -1,14 +1,17 @@ //! Implements the [SolidityCompiler] trait with solc for //! compiling contracts to EVM bytecode. -use std::{path::PathBuf, process::Stdio}; +use std::{collections::HashMap, path::PathBuf, process::Stdio}; use revive_dt_common::types::VersionOrRequirement; use revive_dt_config::Arguments; use super::constants::SOLC_VERSION_SUPPORTING_VIA_YUL_IR; use super::utils; -use crate::{CompilerInput, CompilerOutput, ModeOptimizerSetting, ModePipeline, SolidityCompiler}; +use crate::{ + CompilerInput, CompilerOutput, ModeOptimizerSetting, ModePipeline, SolcCompilerInformation, + SolidityCompiler, +}; use anyhow::Context; use foundry_compilers_artifacts::{ @@ -23,8 +26,6 @@ use tokio::{io::AsyncWriteExt, process::Command as AsyncCommand}; #[derive(Debug)] pub struct Solc { - // Enable wasm compilation. - wasm: bool, // Where to cache artifacts. cache_directory: PathBuf, // We'll use this version when no explicit version requirement @@ -51,11 +52,13 @@ impl SolidityCompiler for Solc { }: CompilerInput, _: Self::Options, ) -> anyhow::Result { - let solc_version = solc_version + let solc_version_req = solc_version .unwrap_or_else(|| VersionOrRequirement::version_to_requirement(&self.solc_version)); let solc_path = - revive_dt_solc_binaries::download_solc(&self.cache_directory, solc_version, self.wasm) + revive_dt_solc_binaries::download_solc(&self.cache_directory, solc_version_req, false) .await?; + let solc_version = utils::solc_version(&solc_path).await?; + let compiler_supports_via_ir = utils::solc_version(&solc_path).await? >= SOLC_VERSION_SUPPORTING_VIA_YUL_IR; @@ -194,10 +197,9 @@ impl SolidityCompiler for Solc { "Compiled successfully" ); - let mut compiler_output = CompilerOutput::default(); + let mut compiled_contracts = HashMap::>::new(); for (contract_path, contracts) in parsed.contracts { - let map = compiler_output - .contracts + let map = compiled_contracts .entry(contract_path.canonicalize().with_context(|| { format!( "Failed to canonicalize contract path {}", @@ -221,12 +223,17 @@ impl SolidityCompiler for Solc { } } - Ok(compiler_output) + Ok(CompilerOutput { + solc: SolcCompilerInformation { + version: solc_version, + path: solc_path, + }, + contracts: compiled_contracts, + }) } fn new(config: &Arguments) -> Self { Self { - wasm: config.wasm, cache_directory: config.directory().to_path_buf(), solc_version: config.solc.clone(), } diff --git a/crates/core/src/cached_compiler.rs b/crates/core/src/cached_compiler.rs index cdac31f..3e48b17 100644 --- a/crates/core/src/cached_compiler.rs +++ b/crates/core/src/cached_compiler.rs @@ -9,7 +9,7 @@ use std::{ use futures::FutureExt; use revive_dt_common::iterators::FilesWithExtensionIterator; -use revive_dt_compiler::{Compiler, CompilerInput, CompilerOutput, Mode}; +use revive_dt_compiler::{Compiler, CompilerInput, CompilerOutput, Mode, SolcCompilerInformation}; use revive_dt_config::Arguments; use revive_dt_format::metadata::{ContractIdent, ContractInstance, Metadata}; use revive_dt_solc_binaries::solc_version; @@ -57,29 +57,23 @@ impl CachedCompiler { mode: &Mode, config: &Arguments, deployed_libraries: Option<&HashMap>, - compilation_success_report_callback: impl Fn( - Version, - PathBuf, - bool, - Option, - CompilerOutput, - ) + Clone, + compilation_success_report_callback: impl Fn(bool, Option, CompilerOutput) + + Clone, compilation_failure_report_callback: impl Fn( - Option, - Option, + Option, Option, String, ), - ) -> Result<(CompilerOutput, Version)> { + ) -> Result { static CACHE_KEY_LOCK: Lazy>>>> = Lazy::new(Default::default); - let compiler_version_or_requirement = mode.compiler_version_to_use(config.solc.clone()); - let compiler_version = solc_version(compiler_version_or_requirement, config.wasm).await?; + let solc_version_or_requirement = mode.compiler_version_to_use(config.solc.clone()); + let solc_version = solc_version(solc_version_or_requirement, false).await?; let cache_key = CacheKey { platform_key: P::config_id().to_string(), - compiler_version: compiler_version.clone(), + compiler_version: solc_version.clone(), metadata_file_path: metadata_file_path.as_ref().to_path_buf(), solc_mode: mode.clone(), }; @@ -146,13 +140,11 @@ impl CachedCompiler { match self.0.get(&cache_key).await { Some(cache_value) => { - // compilation_success_report_callback( - // compiler_version.clone(), - // compiler_path, - // true, - // None, - // cache_value.compiler_output.clone(), - // ); + compilation_success_report_callback( + true, + None, + cache_value.compiler_output.clone(), + ); cache_value.compiler_output } None => { @@ -165,7 +157,7 @@ impl CachedCompiler { } }; - Ok((compiled_contracts, compiler_version)) + Ok(compiled_contracts) } } @@ -176,16 +168,9 @@ async fn compile_contracts( config: &Arguments, mode: &Mode, deployed_libraries: Option<&HashMap>, - compilation_success_report_callback: impl Fn( - Version, - PathBuf, - bool, - Option, - CompilerOutput, - ), + compilation_success_report_callback: impl Fn(bool, Option, CompilerOutput), compilation_failure_report_callback: impl Fn( - Option, - Option, + Option, Option, String, ), @@ -204,15 +189,8 @@ async fn compile_contracts( // Adding the contract sources to the compiler. .try_then(|compiler| { files_to_compile.try_fold(compiler, |compiler, path| compiler.with_source(path)) - // }) - // .inspect_err(|err| { - // compilation_failure_report_callback( - // Some(compiler_version.clone()), - // Some(compiler_path.as_ref().to_path_buf()), - // None, - // format!("{err:#}"), - // ) - })? + }) + .inspect_err(|err| compilation_failure_report_callback(None, None, format!("{err:#}")))? // Adding the deployed libraries to the compiler. .then(|compiler| { deployed_libraries @@ -233,22 +211,16 @@ async fn compile_contracts( let compiler_output = compiler .try_build(config) .await - // .inspect_err(|err| { - // compilation_failure_report_callback( - // Some(compiler_version.clone()), - // Some(compiler_path.as_ref().to_path_buf()), - // Some(compiler_input.clone()), - // format!("{err:#}"), - // ) - // }) + .inspect_err(|err| { + compilation_failure_report_callback( + None, + Some(compiler_input.clone()), + format!("{err:#}"), + ) + }) .context("Failed to configure compiler with sources and options")?; - // compilation_success_report_callback( - // compiler_version, - // compiler_path.as_ref().to_path_buf(), - // false, - // Some(compiler_input), - // compiler_output.clone(), - // ); + + compilation_success_report_callback(false, Some(compiler_input), compiler_output.clone()); Ok(compiler_output) } diff --git a/crates/core/src/main.rs b/crates/core/src/main.rs index 638f817..7c13aab 100644 --- a/crates/core/src/main.rs +++ b/crates/core/src/main.rs @@ -18,12 +18,12 @@ use futures::StreamExt; use futures::stream; use indexmap::IndexMap; use revive_dt_node_interaction::EthereumNode; -use tempfile::TempDir; -use tokio::{join, try_join}; use revive_dt_report::{ NodeDesignation, ReportAggregator, Reporter, ReporterEvent, TestCaseStatus, TestSpecificReporter, TestSpecifier, }; +use tempfile::TempDir; +use tokio::{join, try_join}; use tracing::{debug, info, info_span, instrument}; use tracing_appender::non_blocking::WorkerGuard; use tracing_subscriber::{EnvFilter, FmtSubscriber}; @@ -612,18 +612,14 @@ where .execution_specific_reporter(follower_node.id(), NodeDesignation::Follower); let ( - ( - CompilerOutput { - contracts: leader_pre_link_contracts, - }, - _, - ), - ( - CompilerOutput { - contracts: follower_pre_link_contracts, - }, - _, - ), + CompilerOutput { + contracts: leader_pre_link_contracts, + .. + }, + CompilerOutput { + contracts: follower_pre_link_contracts, + .. + }, ) = try_join!( cached_compiler.compile_contracts::( test.metadata, @@ -631,22 +627,19 @@ where &test.mode, config, None, - |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| { + |is_cached, compiler_input, compiler_output| { leader_reporter .report_pre_link_contracts_compilation_succeeded_event( - compiler_version, - compiler_path, is_cached, compiler_input, compiler_output, ) .expect("Can't fail") }, - |compiler_version, compiler_path, compiler_input, failure_reason| { + |solc_info, compiler_input, failure_reason| { leader_reporter .report_pre_link_contracts_compilation_failed_event( - compiler_version, - compiler_path, + solc_info, compiler_input, failure_reason, ) @@ -659,22 +652,19 @@ where &test.mode, config, None, - |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| { + |is_cached, compiler_input, compiler_output| { follower_reporter .report_pre_link_contracts_compilation_succeeded_event( - compiler_version, - compiler_path, is_cached, compiler_input, compiler_output, ) .expect("Can't fail") }, - |compiler_version, compiler_path, compiler_input, failure_reason| { + |solc_info, compiler_input, failure_reason| { follower_reporter .report_pre_link_contracts_compilation_failed_event( - compiler_version, - compiler_path, + solc_info, compiler_input, failure_reason, ) @@ -811,18 +801,14 @@ where } let ( - ( - CompilerOutput { - contracts: leader_post_link_contracts, - }, - leader_compiler_version, - ), - ( - CompilerOutput { - contracts: follower_post_link_contracts, - }, - follower_compiler_version, - ), + CompilerOutput { + solc: leader_solc_info, + contracts: leader_post_link_contracts, + }, + CompilerOutput { + solc: follower_solc_info, + contracts: follower_post_link_contracts, + }, ) = try_join!( cached_compiler.compile_contracts::( test.metadata, @@ -830,22 +816,19 @@ where &test.mode, config, leader_deployed_libraries.as_ref(), - |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| { + |is_cached, compiler_input, compiler_output| { leader_reporter .report_post_link_contracts_compilation_succeeded_event( - compiler_version, - compiler_path, is_cached, compiler_input, compiler_output, ) .expect("Can't fail") }, - |compiler_version, compiler_path, compiler_input, failure_reason| { + |solc_info, compiler_input, failure_reason| { leader_reporter .report_post_link_contracts_compilation_failed_event( - compiler_version, - compiler_path, + solc_info, compiler_input, failure_reason, ) @@ -858,22 +841,19 @@ where &test.mode, config, follower_deployed_libraries.as_ref(), - |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| { + |is_cached, compiler_input, compiler_output| { follower_reporter .report_post_link_contracts_compilation_succeeded_event( - compiler_version, - compiler_path, is_cached, compiler_input, compiler_output, ) .expect("Can't fail") }, - |compiler_version, compiler_path, compiler_input, failure_reason| { + |solc_info, compiler_input, failure_reason| { follower_reporter .report_post_link_contracts_compilation_failed_event( - compiler_version, - compiler_path, + solc_info, compiler_input, failure_reason, ) @@ -884,13 +864,13 @@ where .context("Failed to compile post-link contracts for leader/follower in parallel")?; let leader_state = CaseState::::new( - leader_compiler_version, + leader_solc_info.version, leader_post_link_contracts, leader_deployed_libraries.unwrap_or_default(), leader_reporter, ); let follower_state = CaseState::::new( - follower_compiler_version, + follower_solc_info.version, follower_post_link_contracts, follower_deployed_libraries.unwrap_or_default(), follower_reporter, @@ -963,8 +943,8 @@ async fn compile_corpus( &mode, config, None, - |_, _, _, _, _| {}, - |_, _, _, _| {}, + |_, _, _| {}, + |_, _, _| {}, ) .await; } @@ -976,8 +956,8 @@ async fn compile_corpus( &mode, config, None, - |_, _, _, _, _| {}, - |_, _, _, _| {}, + |_, _, _| {}, + |_, _, _| {}, ) .await; } diff --git a/crates/report/src/aggregator.rs b/crates/report/src/aggregator.rs index 913b0d5..fe98c09 100644 --- a/crates/report/src/aggregator.rs +++ b/crates/report/src/aggregator.rs @@ -4,17 +4,15 @@ use std::{ collections::{BTreeMap, BTreeSet, HashMap, HashSet}, fs::OpenOptions, - path::PathBuf, time::{SystemTime, UNIX_EPOCH}, }; use alloy_primitives::Address; use anyhow::{Context as _, Result}; use indexmap::IndexMap; -use revive_dt_compiler::{CompilerInput, CompilerOutput, Mode}; +use revive_dt_compiler::{CompilerInput, CompilerOutput, Mode, SolcCompilerInformation}; use revive_dt_config::{Arguments, TestingPlatform}; use revive_dt_format::{case::CaseIdx, corpus::Corpus, metadata::ContractInstance}; -use semver::Version; use serde::Serialize; use serde_with::{DisplayFromStr, serde_as}; use tokio::sync::{ @@ -292,6 +290,7 @@ impl ReportAggregator { } else { None }; + let solc_info = event.compiler_output.solc.clone(); let compiler_output = if include_output { Some(event.compiler_output) } else { @@ -300,8 +299,7 @@ impl ReportAggregator { execution_information.pre_link_compilation_status = Some(CompilationStatus::Success { is_cached: event.is_cached, - compiler_version: event.compiler_version, - compiler_path: event.compiler_path, + solc_info, compiler_input, compiler_output, }); @@ -321,6 +319,7 @@ impl ReportAggregator { } else { None }; + let solc_info = event.compiler_output.solc.clone(); let compiler_output = if include_output { Some(event.compiler_output) } else { @@ -329,8 +328,7 @@ impl ReportAggregator { execution_information.post_link_compilation_status = Some(CompilationStatus::Success { is_cached: event.is_cached, - compiler_version: event.compiler_version, - compiler_path: event.compiler_path, + solc_info, compiler_input, compiler_output, }); @@ -352,8 +350,7 @@ impl ReportAggregator { execution_information.pre_link_compilation_status = Some(CompilationStatus::Failure { reason: event.reason, - compiler_version: event.compiler_version, - compiler_path: event.compiler_path, + solc_info: event.solc_info, compiler_input, }); } @@ -374,8 +371,7 @@ impl ReportAggregator { execution_information.post_link_compilation_status = Some(CompilationStatus::Failure { reason: event.reason, - compiler_version: event.compiler_version, - compiler_path: event.compiler_path, + solc_info: event.solc_info, compiler_input, }); } @@ -528,10 +524,8 @@ pub enum CompilationStatus { Success { /// A flag with information on whether the compilation artifacts were cached or not. is_cached: bool, - /// The version of the compiler used to compile the contracts. - compiler_version: Version, - /// The path of the compiler used to compile the contracts. - compiler_path: PathBuf, + /// The version and path of the solc compiler used to compile the contracts. + solc_info: SolcCompilerInformation, /// The input provided to the compiler to compile the contracts. This is only included if /// the appropriate flag is set in the CLI configuration and if the contracts were not /// cached and the compiler was invoked. @@ -546,12 +540,8 @@ pub enum CompilationStatus { Failure { /// The failure reason. reason: String, - /// The version of the compiler used to compile the contracts. - #[serde(skip_serializing_if = "Option::is_none")] - compiler_version: Option, - /// The path of the compiler used to compile the contracts. - #[serde(skip_serializing_if = "Option::is_none")] - compiler_path: Option, + /// The version and path of the solc compiler used to compile the contracts. + solc_info: Option, /// The input provided to the compiler to compile the contracts. This is only included if /// the appropriate flag is set in the CLI configuration and if the contracts were not /// cached and the compiler was invoked. diff --git a/crates/report/src/runner_event.rs b/crates/report/src/runner_event.rs index bdd6c0e..d52738a 100644 --- a/crates/report/src/runner_event.rs +++ b/crates/report/src/runner_event.rs @@ -1,16 +1,15 @@ //! The types associated with the events sent by the runner to the reporter. #![allow(dead_code)] -use std::{collections::BTreeMap, path::PathBuf, sync::Arc}; +use std::{collections::BTreeMap, sync::Arc}; use alloy_primitives::Address; use anyhow::Context as _; use indexmap::IndexMap; -use revive_dt_compiler::{CompilerInput, CompilerOutput}; +use revive_dt_compiler::{CompilerInput, CompilerOutput, SolcCompilerInformation}; use revive_dt_config::TestingPlatform; use revive_dt_format::metadata::Metadata; use revive_dt_format::{corpus::Corpus, metadata::ContractInstance}; -use semver::Version; use tokio::sync::{broadcast, oneshot}; use crate::{ExecutionSpecifier, ReporterEvent, TestSpecifier, common::MetadataFilePath}; @@ -547,10 +546,6 @@ define_event! { PreLinkContractsCompilationSucceeded { /// A specifier for the execution that's taking place. execution_specifier: Arc, - /// The version of the compiler used to compile the contracts. - compiler_version: Version, - /// The path of the compiler used to compile the contracts. - compiler_path: PathBuf, /// A flag of whether the contract bytecode and ABI were cached or if they were compiled /// anew. is_cached: bool, @@ -565,10 +560,6 @@ define_event! { PostLinkContractsCompilationSucceeded { /// A specifier for the execution that's taking place. execution_specifier: Arc, - /// The version of the compiler used to compile the contracts. - compiler_version: Version, - /// The path of the compiler used to compile the contracts. - compiler_path: PathBuf, /// A flag of whether the contract bytecode and ABI were cached or if they were compiled /// anew. is_cached: bool, @@ -583,10 +574,8 @@ define_event! { PreLinkContractsCompilationFailed { /// A specifier for the execution that's taking place. execution_specifier: Arc, - /// The version of the compiler used to compile the contracts. - compiler_version: Option, - /// The path of the compiler used to compile the contracts. - compiler_path: Option, + /// The version and path of the solc compiler used to compile the contracts. + solc_info: Option, /// The input provided to the compiler - this is optional and not provided if the /// contracts were obtained from the cache. compiler_input: Option, @@ -598,10 +587,8 @@ define_event! { PostLinkContractsCompilationFailed { /// A specifier for the execution that's taking place. execution_specifier: Arc, - /// The version of the compiler used to compile the contracts. - compiler_version: Option, - /// The path of the compiler used to compile the contracts. - compiler_path: Option, + /// The version and path of the solc compiler used to compile the contracts. + solc_info: Option, /// The input provided to the compiler - this is optional and not provided if the /// contracts were obtained from the cache. compiler_input: Option, diff --git a/crates/solc-binaries/src/lib.rs b/crates/solc-binaries/src/lib.rs index c87cd8b..3995477 100644 --- a/crates/solc-binaries/src/lib.rs +++ b/crates/solc-binaries/src/lib.rs @@ -3,10 +3,10 @@ //! //! [0]: https://binaries.soliditylang.org -use std::path::{Path, PathBuf}; use cache::get_or_download; use download::SolcDownloader; use semver::Version; +use std::path::{Path, PathBuf}; use revive_dt_common::types::VersionOrRequirement;