From b924c24fff0d01e4e59ecd35b6fad1856d4f9cce Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Fri, 26 Nov 2021 21:21:27 +0200 Subject: [PATCH 1/4] feat(solc): add tracing --- ethers-solc/src/cache.rs | 12 +++++++++-- ethers-solc/src/lib.rs | 45 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/ethers-solc/src/cache.rs b/ethers-solc/src/cache.rs index e6815ac89..e82e0ddb3 100644 --- a/ethers-solc/src/cache.rs +++ b/ethers-solc/src/cache.rs @@ -43,15 +43,23 @@ impl SolFilesCache { } /// Reads the cache json file from the given path + #[tracing::instrument(skip_all, name = "sol-files-cache::read")] pub fn read(path: impl AsRef) -> Result { + tracing::trace!("reading solfiles cache"); let file = fs::File::open(path.as_ref())?; - Ok(serde_json::from_reader(file)?) + let file = std::io::BufReader::new(file); + let cache = serde_json::from_reader(file)?; + tracing::trace!("done"); + Ok(cache) } /// Write the cache to json file pub fn write(&self, path: impl AsRef) -> Result<()> { let file = fs::File::create(path.as_ref())?; - Ok(serde_json::to_writer_pretty(file, self)?) + tracing::trace!("writing cache to json"); + serde_json::to_writer_pretty(file, self)?; + tracing::trace!("done"); + Ok(()) } pub fn remove_missing_files(&mut self) { diff --git a/ethers-solc/src/lib.rs b/ethers-solc/src/lib.rs index dd64ac67c..ee0aa05b5 100644 --- a/ethers-solc/src/lib.rs +++ b/ethers-solc/src/lib.rs @@ -90,15 +90,18 @@ impl Project { } impl Project { + #[tracing::instrument(skip_all, name = "Project::write_cache_file")] fn write_cache_file( &self, sources: Sources, artifacts: Vec<(PathBuf, Vec)>, ) -> Result<()> { + tracing::trace!("inserting files to cache"); let mut cache = SolFilesCache::builder() .root(&self.paths.root) .solc_config(self.solc_config.clone()) .insert_files(sources, Some(self.paths.cache.clone()))?; + tracing::trace!("files inserted"); // add the artifacts for each file to the cache entry for (file, artifacts) in artifacts { @@ -107,13 +110,18 @@ impl Project { } } + tracing::trace!("writing files to disk"); if let Some(cache_dir) = self.paths.cache.parent() { fs::create_dir_all(cache_dir)? } - cache.write(&self.paths.cache) + cache.write(&self.paths.cache)?; + tracing::trace!("files written"); + + Ok(()) } /// Returns all sources found under the project's sources path + #[tracing::instrument(skip_all, fields(name = "sources"))] pub fn sources(&self) -> io::Result { Source::read_all_from(self.paths.sources.as_path()) } @@ -167,11 +175,15 @@ impl Project { /// NB: If the `svm` feature is enabled, this function will automatically detect /// solc versions across files. + #[tracing::instrument(skip_all, name = "compile")] pub fn compile(&self) -> Result> { + tracing::trace!("sources"); let sources = self.sources()?; + tracing::trace!("done"); #[cfg(all(feature = "svm", feature = "async"))] if self.auto_detect { + tracing::trace!("auto-compile"); return self.svm_compile(sources) } @@ -183,15 +195,20 @@ impl Project { } #[cfg(all(feature = "svm", feature = "async"))] + #[tracing::instrument(skip(self, sources))] fn svm_compile(&self, sources: Sources) -> Result> { // split them by version let mut sources_by_version = BTreeMap::new(); // we store the solc versions by path, in case there exists a corrupt solc binary let mut solc_versions = HashMap::new(); + // TODO: Rayon + // tracing::trace!("parsing sources"); for (path, source) in sources.into_iter() { // will detect and install the solc version + // tracing::trace!("finding version {}", path.display()); let version = Solc::detect_version(&source)?; + // tracing::trace!("found {}", version); // gets the solc binary for that version, it is expected tha this will succeed // AND find the solc since it was installed right above let mut solc = Solc::find_svm_installed_version(version.to_string())? @@ -204,21 +221,31 @@ impl Project { let entry = sources_by_version.entry(solc).or_insert_with(BTreeMap::new); entry.insert(path.clone(), source); } + // tracing::trace!("done"); let mut compiled = ProjectCompileOutput::with_ignored_errors(self.ignored_error_codes.clone()); // run the compilation step for each version + tracing::trace!("compiling all versions"); for (solc, sources) in sources_by_version { + let span = tracing::trace_span!("solc", "{}", solc.version_short()?); + let _enter = span.enter(); + // verify that this solc version's checksum matches the checksum found remotely. If // not, re-install the same version. let version = solc_versions.get(&solc.solc).unwrap(); if let Err(_e) = solc.verify_checksum() { + tracing::trace!("missing version, redownloading..."); Solc::blocking_install(version)?; + tracing::trace!("done."); } // once matched, proceed to compile with it + tracing::trace!("compiling_with_version"); compiled.extend(self.compile_with_version(&solc, sources)?); + tracing::trace!("done compiling_with_version"); } + tracing::trace!("done compiling all versions"); Ok(compiled) } @@ -228,6 +255,8 @@ impl Project { solc: &Solc, mut sources: Sources, ) -> Result> { + let span = tracing::trace_span!("compiling"); + let _enter = span.enter(); // add all libraries to the source set while keeping track of their actual disk path // (`contracts/contract.sol` -> `/Users/.../contracts.sol`) let mut source_name_to_path = HashMap::new(); @@ -235,17 +264,21 @@ impl Project { // `contracts/contract.sol`) let mut path_to_source_name = HashMap::new(); + tracing::trace!("resolving libraries"); for (import, (source, path)) in self.resolved_libraries(&sources)? { // inserting with absolute path here and keep track of the source name <-> path mappings sources.insert(path.clone(), source); path_to_source_name.insert(path.clone(), import.clone()); source_name_to_path.insert(import, path); } + tracing::trace!("done resolving libraries"); // If there's a cache set, filter to only re-compile the files which were changed let (sources, cached_artifacts) = if self.cached && self.paths.cache.exists() { + tracing::trace!("reading solfiles cache for incremental compilation"); let mut cache = SolFilesCache::read(&self.paths.cache)?; cache.remove_missing_files(); + tracing::trace!("done reading solfiles cache for incremental compilation"); let changed_files = cache.get_changed_or_missing_artifacts_files::( sources, Some(&self.solc_config), @@ -253,12 +286,17 @@ impl Project { ); let cached_artifacts = if self.paths.artifacts.exists() { - cache.read_artifacts::(&self.paths.artifacts)? + tracing::trace!("reading artifacts from cache.."); + let artifacts = cache.read_artifacts::(&self.paths.artifacts)?; + tracing::trace!("done reading artifacts from cache"); + artifacts } else { BTreeMap::default() }; + // if nothing changed and all artifacts still exist if changed_files.is_empty() { + tracing::trace!("no change"); return Ok(ProjectCompileOutput::from_unchanged(cached_artifacts)) } // There are changed files and maybe some cached files @@ -273,7 +311,9 @@ impl Project { let input = CompilerInput::with_sources(sources) .normalize_evm_version(&solc.version()?) .with_remappings(self.paths.remappings.clone()); + tracing::trace!("calling solc"); let output = solc.compile(&input)?; + tracing::trace!("done calling solc"); if output.has_error() { return Ok(ProjectCompileOutput::from_compiler_output( output, @@ -304,6 +344,7 @@ impl Project { if !self.no_artifacts { Artifacts::on_output(&output, &self.paths)?; } + Ok(ProjectCompileOutput::from_compiler_output_and_cache( output, cached_artifacts, From 54602c9210d10eb39731dd5d00b484a91c7d64c5 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Sat, 27 Nov 2021 13:05:21 +0200 Subject: [PATCH 2/4] chore: apply suggestions from code review Co-authored-by: Matthias Seitz --- ethers-solc/src/cache.rs | 6 +++--- ethers-solc/src/lib.rs | 10 ++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ethers-solc/src/cache.rs b/ethers-solc/src/cache.rs index e82e0ddb3..ba08deb54 100644 --- a/ethers-solc/src/cache.rs +++ b/ethers-solc/src/cache.rs @@ -45,7 +45,7 @@ impl SolFilesCache { /// Reads the cache json file from the given path #[tracing::instrument(skip_all, name = "sol-files-cache::read")] pub fn read(path: impl AsRef) -> Result { - tracing::trace!("reading solfiles cache"); + tracing::trace!("reading solfiles cache at {}", path.display()); let file = fs::File::open(path.as_ref())?; let file = std::io::BufReader::new(file); let cache = serde_json::from_reader(file)?; @@ -56,9 +56,9 @@ impl SolFilesCache { /// Write the cache to json file pub fn write(&self, path: impl AsRef) -> Result<()> { let file = fs::File::create(path.as_ref())?; - tracing::trace!("writing cache to json"); + tracing::trace!("writing cache to json file"); serde_json::to_writer_pretty(file, self)?; - tracing::trace!("done"); + tracing::trace!("cache file located: {}", path.display()); Ok(()) } diff --git a/ethers-solc/src/lib.rs b/ethers-solc/src/lib.rs index ee0aa05b5..c28e876c6 100644 --- a/ethers-solc/src/lib.rs +++ b/ethers-solc/src/lib.rs @@ -110,12 +110,10 @@ impl Project { } } - tracing::trace!("writing files to disk"); if let Some(cache_dir) = self.paths.cache.parent() { fs::create_dir_all(cache_dir)? } cache.write(&self.paths.cache)?; - tracing::trace!("files written"); Ok(()) } @@ -227,7 +225,7 @@ impl Project { ProjectCompileOutput::with_ignored_errors(self.ignored_error_codes.clone()); // run the compilation step for each version - tracing::trace!("compiling all versions"); + tracing::trace!("compiling sources with viable solc versions"); for (solc, sources) in sources_by_version { let span = tracing::trace_span!("solc", "{}", solc.version_short()?); let _enter = span.enter(); @@ -245,7 +243,7 @@ impl Project { compiled.extend(self.compile_with_version(&solc, sources)?); tracing::trace!("done compiling_with_version"); } - tracing::trace!("done compiling all versions"); + tracing::trace!("compiled sources with viable solc versions"); Ok(compiled) } @@ -271,7 +269,7 @@ impl Project { path_to_source_name.insert(path.clone(), import.clone()); source_name_to_path.insert(import, path); } - tracing::trace!("done resolving libraries"); + tracing::trace!("resolved libraries"); // If there's a cache set, filter to only re-compile the files which were changed let (sources, cached_artifacts) = if self.cached && self.paths.cache.exists() { @@ -313,7 +311,7 @@ impl Project { .with_remappings(self.paths.remappings.clone()); tracing::trace!("calling solc"); let output = solc.compile(&input)?; - tracing::trace!("done calling solc"); + tracing::trace!("compiled input, output has error: {}", output.has_error()); if output.has_error() { return Ok(ProjectCompileOutput::from_compiler_output( output, From 2a8eeacee7bbb626712c6e88193fa9ba93b7a89c Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Sun, 28 Nov 2021 19:09:16 +0200 Subject: [PATCH 3/4] chore: fix compilation error --- ethers-solc/src/cache.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ethers-solc/src/cache.rs b/ethers-solc/src/cache.rs index ba08deb54..6eeaa91fe 100644 --- a/ethers-solc/src/cache.rs +++ b/ethers-solc/src/cache.rs @@ -45,8 +45,9 @@ impl SolFilesCache { /// Reads the cache json file from the given path #[tracing::instrument(skip_all, name = "sol-files-cache::read")] pub fn read(path: impl AsRef) -> Result { + let path = path.as_ref(); tracing::trace!("reading solfiles cache at {}", path.display()); - let file = fs::File::open(path.as_ref())?; + let file = fs::File::open(path)?; let file = std::io::BufReader::new(file); let cache = serde_json::from_reader(file)?; tracing::trace!("done"); @@ -55,7 +56,8 @@ impl SolFilesCache { /// Write the cache to json file pub fn write(&self, path: impl AsRef) -> Result<()> { - let file = fs::File::create(path.as_ref())?; + let path = path.as_ref(); + let file = fs::File::create(path)?; tracing::trace!("writing cache to json file"); serde_json::to_writer_pretty(file, self)?; tracing::trace!("cache file located: {}", path.display()); From 7717703f4f83afdee7aff1d2edc230e891487976 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Sun, 28 Nov 2021 19:14:19 +0200 Subject: [PATCH 4/4] chore: adjust log --- ethers-solc/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethers-solc/src/lib.rs b/ethers-solc/src/lib.rs index c28e876c6..be2b4eabc 100644 --- a/ethers-solc/src/lib.rs +++ b/ethers-solc/src/lib.rs @@ -234,7 +234,7 @@ impl Project { // not, re-install the same version. let version = solc_versions.get(&solc.solc).unwrap(); if let Err(_e) = solc.verify_checksum() { - tracing::trace!("missing version, redownloading..."); + tracing::trace!("corrupted solc version, redownloading..."); Solc::blocking_install(version)?; tracing::trace!("done."); }