mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-06-10 17:21:02 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9aa26a99d6 | |||
| 02f853699e | |||
| fde303f549 | |||
| e5a751f507 | |||
| d9d62b1038 | |||
| 71ae3b0f9a | |||
| 8cda6a9726 | |||
| a43d94ea7d | |||
| 6960298438 | |||
| 62cf57d39e | |||
| 3fc26eb03b | |||
| 268437b4d9 | |||
| 27a0a0de0b | |||
| 331705134a |
@@ -44,8 +44,6 @@ pub trait SolidityCompiler {
|
|||||||
pub struct CompilerInput<T: PartialEq + Eq + Hash> {
|
pub struct CompilerInput<T: PartialEq + Eq + Hash> {
|
||||||
pub extra_options: T,
|
pub extra_options: T,
|
||||||
pub input: SolcStandardJsonInput,
|
pub input: SolcStandardJsonInput,
|
||||||
pub allow_paths: Vec<PathBuf>,
|
|
||||||
pub base_path: Option<PathBuf>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The generic compilation output configuration.
|
/// The generic compilation output configuration.
|
||||||
@@ -85,8 +83,8 @@ where
|
|||||||
pub struct Compiler<T: SolidityCompiler> {
|
pub struct Compiler<T: SolidityCompiler> {
|
||||||
input: SolcStandardJsonInput,
|
input: SolcStandardJsonInput,
|
||||||
extra_options: T::Options,
|
extra_options: T::Options,
|
||||||
allow_paths: Vec<PathBuf>,
|
allow_paths: Vec<String>,
|
||||||
base_path: Option<PathBuf>,
|
base_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Compiler<solc::Solc> {
|
impl Default for Compiler<solc::Solc> {
|
||||||
@@ -147,12 +145,12 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allow_path(mut self, path: PathBuf) -> Self {
|
pub fn allow_path(mut self, path: String) -> Self {
|
||||||
self.allow_paths.push(path);
|
self.allow_paths.push(path);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn base_path(mut self, base_path: PathBuf) -> Self {
|
pub fn base_path(mut self, base_path: String) -> Self {
|
||||||
self.base_path = Some(base_path);
|
self.base_path = Some(base_path);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -161,8 +159,6 @@ where
|
|||||||
T::new(solc_path).build(CompilerInput {
|
T::new(solc_path).build(CompilerInput {
|
||||||
extra_options: self.extra_options,
|
extra_options: self.extra_options,
|
||||||
input: self.input,
|
input: self.input,
|
||||||
allow_paths: self.allow_paths,
|
|
||||||
base_path: self.base_path,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,27 +23,13 @@ impl SolidityCompiler for Resolc {
|
|||||||
&self,
|
&self,
|
||||||
input: CompilerInput<Self::Options>,
|
input: CompilerInput<Self::Options>,
|
||||||
) -> anyhow::Result<CompilerOutput<Self::Options>> {
|
) -> anyhow::Result<CompilerOutput<Self::Options>> {
|
||||||
let mut command = Command::new(&self.resolc_path);
|
let mut child = Command::new(&self.resolc_path)
|
||||||
command
|
.arg("--standard-json")
|
||||||
|
.args(&input.extra_options)
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.arg("--standard-json");
|
.spawn()?;
|
||||||
|
|
||||||
if let Some(ref base_path) = input.base_path {
|
|
||||||
command.arg("--base-path").arg(base_path);
|
|
||||||
}
|
|
||||||
if !input.allow_paths.is_empty() {
|
|
||||||
command.arg("--allow-paths").arg(
|
|
||||||
input
|
|
||||||
.allow_paths
|
|
||||||
.iter()
|
|
||||||
.map(|path| path.display().to_string())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(","),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let mut child = command.spawn()?;
|
|
||||||
|
|
||||||
let stdin_pipe = child.stdin.as_mut().expect("stdin must be piped");
|
let stdin_pipe = child.stdin.as_mut().expect("stdin must be piped");
|
||||||
serde_json::to_writer(stdin_pipe, &input.input)?;
|
serde_json::to_writer(stdin_pipe, &input.input)?;
|
||||||
@@ -69,22 +55,13 @@ impl SolidityCompiler for Resolc {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let parsed = serde_json::from_slice::<SolcStandardJsonOutput>(&stdout).map_err(|e| {
|
let parsed: SolcStandardJsonOutput = serde_json::from_slice(&stdout).map_err(|e| {
|
||||||
anyhow::anyhow!(
|
anyhow::anyhow!(
|
||||||
"failed to parse resolc JSON output: {e}\nstderr: {}",
|
"failed to parse resolc JSON output: {e}\nstderr: {}",
|
||||||
String::from_utf8_lossy(&stderr)
|
String::from_utf8_lossy(&stderr)
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Detecting if the compiler output contained errors and reporting them through logs and
|
|
||||||
// errors instead of returning the compiler output that might contain errors.
|
|
||||||
for error in parsed.errors.iter().flatten() {
|
|
||||||
if error.severity == "error" {
|
|
||||||
tracing::error!(?error, ?input, "Encountered an error in the compilation");
|
|
||||||
anyhow::bail!("Encountered an error in the compilation: {error}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(CompilerOutput {
|
Ok(CompilerOutput {
|
||||||
input,
|
input,
|
||||||
output: parsed,
|
output: parsed,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use std::{
|
|||||||
use crate::{CompilerInput, CompilerOutput, SolidityCompiler};
|
use crate::{CompilerInput, CompilerOutput, SolidityCompiler};
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
use revive_dt_solc_binaries::download_solc;
|
use revive_dt_solc_binaries::download_solc;
|
||||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
|
||||||
|
|
||||||
pub struct Solc {
|
pub struct Solc {
|
||||||
solc_path: PathBuf,
|
solc_path: PathBuf,
|
||||||
@@ -22,27 +21,12 @@ impl SolidityCompiler for Solc {
|
|||||||
&self,
|
&self,
|
||||||
input: CompilerInput<Self::Options>,
|
input: CompilerInput<Self::Options>,
|
||||||
) -> anyhow::Result<CompilerOutput<Self::Options>> {
|
) -> anyhow::Result<CompilerOutput<Self::Options>> {
|
||||||
let mut command = Command::new(&self.solc_path);
|
let mut child = Command::new(&self.solc_path)
|
||||||
command
|
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.arg("--standard-json");
|
.arg("--standard-json")
|
||||||
|
.spawn()?;
|
||||||
if let Some(ref base_path) = input.base_path {
|
|
||||||
command.arg("--base-path").arg(base_path);
|
|
||||||
}
|
|
||||||
if !input.allow_paths.is_empty() {
|
|
||||||
command.arg("--allow-paths").arg(
|
|
||||||
input
|
|
||||||
.allow_paths
|
|
||||||
.iter()
|
|
||||||
.map(|path| path.display().to_string())
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join(","),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let mut child = command.spawn()?;
|
|
||||||
|
|
||||||
let stdin = child.stdin.as_mut().expect("should be piped");
|
let stdin = child.stdin.as_mut().expect("should be piped");
|
||||||
serde_json::to_writer(stdin, &input.input)?;
|
serde_json::to_writer(stdin, &input.input)?;
|
||||||
@@ -58,26 +42,9 @@ impl SolidityCompiler for Solc {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let parsed =
|
|
||||||
serde_json::from_slice::<SolcStandardJsonOutput>(&output.stdout).map_err(|e| {
|
|
||||||
anyhow::anyhow!(
|
|
||||||
"failed to parse resolc JSON output: {e}\nstderr: {}",
|
|
||||||
String::from_utf8_lossy(&output.stdout)
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Detecting if the compiler output contained errors and reporting them through logs and
|
|
||||||
// errors instead of returning the compiler output that might contain errors.
|
|
||||||
for error in parsed.errors.iter().flatten() {
|
|
||||||
if error.severity == "error" {
|
|
||||||
tracing::error!(?error, ?input, "Encountered an error in the compilation");
|
|
||||||
anyhow::bail!("Encountered an error in the compilation: {error}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(CompilerOutput {
|
Ok(CompilerOutput {
|
||||||
input,
|
input,
|
||||||
output: parsed,
|
output: serde_json::from_slice(&output.stdout)?,
|
||||||
error: None,
|
error: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,13 +69,14 @@ where
|
|||||||
anyhow::bail!("unsupported solc version: {:?}", &mode.solc_version);
|
anyhow::bail!("unsupported solc version: {:?}", &mode.solc_version);
|
||||||
};
|
};
|
||||||
|
|
||||||
let compiler = Compiler::<T::Compiler>::new()
|
let mut compiler = Compiler::<T::Compiler>::new()
|
||||||
.allow_path(metadata.directory()?)
|
.base_path(metadata.directory()?.display().to_string())
|
||||||
.solc_optimizer(mode.solc_optimize());
|
.solc_optimizer(mode.solc_optimize());
|
||||||
|
|
||||||
let compiler = FilesWithExtensionIterator::new(metadata.directory()?)
|
for (file, _contract) in metadata.contract_sources()?.values() {
|
||||||
.with_allowed_extension("sol")
|
tracing::debug!("contract source {}", file.display());
|
||||||
.try_fold(compiler, |compiler, path| compiler.with_source(&path))?;
|
compiler = compiler.with_source(file)?;
|
||||||
|
}
|
||||||
|
|
||||||
let mut task = CompilationTask {
|
let mut task = CompilationTask {
|
||||||
json_input: compiler.input(),
|
json_input: compiler.input(),
|
||||||
@@ -179,15 +180,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deploy_contracts(&mut self, input: &Input, node: &T::Blockchain) -> anyhow::Result<()> {
|
pub fn deploy_contracts(&mut self, input: &Input, node: &T::Blockchain) -> anyhow::Result<()> {
|
||||||
let tracing_span = tracing::debug_span!(
|
tracing::debug!(
|
||||||
"Deploying contracts",
|
"Deploying contracts {}, having address {} on node: {}",
|
||||||
?input,
|
&input.instance,
|
||||||
node = std::any::type_name::<T>()
|
&input.caller,
|
||||||
|
std::any::type_name::<T>()
|
||||||
);
|
);
|
||||||
let _guard = tracing_span.enter();
|
|
||||||
|
|
||||||
tracing::debug!(number_of_contracts_to_deploy = self.contracts.len());
|
|
||||||
|
|
||||||
for output in self.contracts.values() {
|
for output in self.contracts.values() {
|
||||||
let Some(contract_map) = &output.contracts else {
|
let Some(contract_map) = &output.contracts else {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
@@ -478,77 +476,3 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator that finds files of a certain extension in the provided directory. You can think of
|
|
||||||
/// this a glob pattern similar to: `${path}/**/*.md`
|
|
||||||
struct FilesWithExtensionIterator {
|
|
||||||
/// The set of allowed extensions that that match the requirement and that should be returned
|
|
||||||
/// when found.
|
|
||||||
allowed_extensions: std::collections::HashSet<std::borrow::Cow<'static, str>>,
|
|
||||||
|
|
||||||
/// The set of directories to visit next. This iterator does BFS and so these directories will
|
|
||||||
/// only be visited if we can't find any files in our state.
|
|
||||||
directories_to_search: Vec<std::path::PathBuf>,
|
|
||||||
|
|
||||||
/// The set of files matching the allowed extensions that were found. If there are entries in
|
|
||||||
/// this vector then they will be returned when the [`Iterator::next`] method is called. If not
|
|
||||||
/// then we visit one of the next directories to visit.
|
|
||||||
///
|
|
||||||
/// [`Iterator`]: std::iter::Iterator
|
|
||||||
files_matching_allowed_extensions: Vec<std::path::PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FilesWithExtensionIterator {
|
|
||||||
fn new(root_directory: std::path::PathBuf) -> Self {
|
|
||||||
Self {
|
|
||||||
allowed_extensions: Default::default(),
|
|
||||||
directories_to_search: vec![root_directory],
|
|
||||||
files_matching_allowed_extensions: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_allowed_extension(
|
|
||||||
mut self,
|
|
||||||
allowed_extension: impl Into<std::borrow::Cow<'static, str>>,
|
|
||||||
) -> Self {
|
|
||||||
self.allowed_extensions.insert(allowed_extension.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for FilesWithExtensionIterator {
|
|
||||||
type Item = std::path::PathBuf;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
if let Some(file_path) = self.files_matching_allowed_extensions.pop() {
|
|
||||||
return Some(file_path);
|
|
||||||
};
|
|
||||||
|
|
||||||
let directory_to_search = self.directories_to_search.pop()?;
|
|
||||||
|
|
||||||
// Read all of the entries in the directory. If we failed to read this dir's entires then we
|
|
||||||
// elect to just ignore it and look in the next directory, we do that by calling the next
|
|
||||||
// method again on the iterator, which is an intentional decision that we made here instead
|
|
||||||
// of panicking.
|
|
||||||
let Ok(dir_entries) = std::fs::read_dir(directory_to_search) else {
|
|
||||||
return self.next();
|
|
||||||
};
|
|
||||||
|
|
||||||
for entry in dir_entries.flatten() {
|
|
||||||
let entry_path = entry.path();
|
|
||||||
if entry_path.is_dir() {
|
|
||||||
self.directories_to_search.push(entry_path)
|
|
||||||
} else if entry_path.is_file()
|
|
||||||
&& entry_path.extension().is_some_and(|ext| {
|
|
||||||
self.allowed_extensions
|
|
||||||
.iter()
|
|
||||||
.any(|allowed| ext.eq_ignore_ascii_case(allowed.as_ref()))
|
|
||||||
})
|
|
||||||
{
|
|
||||||
self.files_matching_allowed_extensions.push(entry_path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -123,14 +123,9 @@ impl Input {
|
|||||||
return Ok(Bytes::default()); // fallback or deployer — no input
|
return Ok(Bytes::default()); // fallback or deployer — no input
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(abi) = deployed_abis.get(&self.instance) else {
|
let abi = deployed_abis
|
||||||
tracing::error!(
|
.get(&self.instance)
|
||||||
contract_name = self.instance,
|
.ok_or_else(|| anyhow::anyhow!("ABI for instance '{}' not found", &self.instance))?;
|
||||||
available_abis = ?deployed_abis.keys().collect::<Vec<_>>(),
|
|
||||||
"Attempted to lookup ABI of contract but it wasn't found"
|
|
||||||
);
|
|
||||||
anyhow::bail!("ABI for instance '{}' not found", &self.instance);
|
|
||||||
};
|
|
||||||
|
|
||||||
tracing::trace!("ABI found for instance: {}", &self.instance);
|
tracing::trace!("ABI found for instance: {}", &self.instance);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user