From 3da5a419fe5ac897b1b983ec50a9c6ed3851265b Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 5 Jan 2022 19:42:07 +0100 Subject: [PATCH] fix(solc): add timeout and error detection for releases lookup (#759) * fix(solc): add timeout and error detection for releases lookup * bump tokio cargo update * fix: move timeout in async block --- Cargo.lock | 9 ++++----- ethers-solc/Cargo.toml | 4 ++-- ethers-solc/src/compile.rs | 33 ++++++++++++++++++++++++++------- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 94f27eb6..529b9cb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3419,11 +3419,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg", "bytes", "libc", "memchr", @@ -3439,9 +3438,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", diff --git a/ethers-solc/Cargo.toml b/ethers-solc/Cargo.toml index 4156028e..7451a285 100644 --- a/ethers-solc/Cargo.toml +++ b/ethers-solc/Cargo.toml @@ -19,7 +19,7 @@ serde_json = "1.0.68" serde = { version = "1.0.130", features = ["derive"] } semver = "1.0.4" walkdir = "2.3.2" -tokio = { version = "1.12.0", default-features = false, features = ["process", "io-util", "fs"], optional = true } +tokio = { version = "1.15.0", default-features = false, features = ["process", "io-util", "fs", "time"], optional = true } futures-util = { version = "^0.3", optional = true } once_cell = "1.8.0" regex = "1.5.4" @@ -50,7 +50,7 @@ getrandom = { version = "0.2", features = ["js"] } criterion = { version = "0.3", features = ["async_tokio"] } pretty_assertions = "1.0.0" tempdir = "0.3.7" -tokio = { version = "1.12.0", features = ["full"] } +tokio = { version = "1.15.0", features = ["full"] } [[bench]] name = "compile_many" diff --git a/ethers-solc/src/compile.rs b/ethers-solc/src/compile.rs index c73ab41a..9377048a 100644 --- a/ethers-solc/src/compile.rs +++ b/ethers-solc/src/compile.rs @@ -48,20 +48,33 @@ static LOCK: Lazy> = Lazy::new(|| Mutex::new(())); #[cfg(all(feature = "svm", feature = "async"))] /// A list of upstream Solc releases, used to check which version /// we should download. -pub static RELEASES: Lazy<(svm::Releases, Vec)> = Lazy::new(|| { +/// The boolean value marks whether there was an error. +pub static RELEASES: Lazy<(svm::Releases, Vec, bool)> = Lazy::new(|| { // Try to download the releases, if it fails default to empty match tokio::runtime::Runtime::new() .expect("could not create tokio rt to get remote releases") - // TODO: Can we make this future timeout at a small time amount so that // we do not degrade startup performance if the consumer has a weak network? - .block_on(svm::all_releases(svm::platform())) - { - Ok(releases) => { + // use a 3 sec timeout for the request which should still be fine for slower connections + .block_on(async { + tokio::time::timeout( + std::time::Duration::from_millis(3000), + svm::all_releases(svm::platform()), + ) + .await + }) { + Ok(Ok(releases)) => { let mut sorted_releases = releases.releases.keys().cloned().collect::>(); sorted_releases.sort(); - (releases, sorted_releases) + (releases, sorted_releases, true) + } + Ok(Err(err)) => { + tracing::error!("{:?}", err); + (svm::Releases::default(), Vec::new(), false) + } + Err(err) => { + tracing::error!("Releases request timed out: {:?}", err); + (svm::Releases::default(), Vec::new(), false) } - Err(_) => (svm::Releases::default(), Vec::new()), } }); @@ -281,6 +294,12 @@ impl Solc { let content = std::fs::read(&version_path).map_err(|err| SolcError::io(err, version_path))?; + if !RELEASES.2 { + // we skip checksum verification because the underlying request to fetch release info + // failed so we have nothing to compare against + return Ok(()) + } + use sha2::Digest; let mut hasher = sha2::Sha256::new(); hasher.update(&content);