Skip to content

Commit 38b4256

Browse files
Added implementation for resolc trait (#12)
Implement the Solidity Compiler trait for resolc
1 parent 8009f58 commit 38b4256

File tree

8 files changed

+115
-12
lines changed

8 files changed

+115
-12
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/compiler/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ rust-version.workspace = true
1111
[dependencies]
1212
anyhow = { workspace = true }
1313
revive-solc-json-interface = { workspace = true }
14+
revive-dt-config = { workspace = true }
15+
revive-dt-solc-binaries = { workspace = true }
1416
revive-common = { workspace = true }
1517
semver = { workspace = true }
1618
serde_json = { workspace = true }
19+
log = { workspace = true }

crates/compiler/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use std::{
99
path::{Path, PathBuf},
1010
};
1111

12+
use revive_dt_config::Arguments;
13+
1214
use revive_common::EVMVersion;
1315
use revive_solc_json_interface::{
1416
SolcStandardJsonInput, SolcStandardJsonInputLanguage, SolcStandardJsonInputSettings,
@@ -33,6 +35,8 @@ pub trait SolidityCompiler {
3335
) -> anyhow::Result<CompilerOutput<Self::Options>>;
3436

3537
fn new(solc_executable: PathBuf) -> Self;
38+
39+
fn get_compiler_executable(config: &Arguments, version: Version) -> anyhow::Result<PathBuf>;
3640
}
3741

3842
/// The generic compilation input configuration.
Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,79 @@
1-
//! Implements the [crate::SolidityCompiler] trait with resolc for
2-
//! compiling contracts to PVM bytecode.
1+
//! Implements the [SolidityCompiler] trait with `resolc` for
2+
//! compiling contracts to PolkaVM (PVM) bytecode.
3+
4+
use std::{
5+
path::PathBuf,
6+
process::{Command, Stdio},
7+
};
8+
9+
use crate::{CompilerInput, CompilerOutput, SolidityCompiler};
10+
use revive_dt_config::Arguments;
11+
use revive_solc_json_interface::SolcStandardJsonOutput;
12+
13+
/// A wrapper around the `resolc` binary, emitting PVM-compatible bytecode.
14+
pub struct Resolc {
15+
/// Path to the `resolc` executable
16+
resolc_path: PathBuf,
17+
}
18+
19+
impl SolidityCompiler for Resolc {
20+
type Options = Vec<String>;
21+
22+
fn build(
23+
&self,
24+
input: CompilerInput<Self::Options>,
25+
) -> anyhow::Result<CompilerOutput<Self::Options>> {
26+
let mut child = Command::new(&self.resolc_path)
27+
.arg("--standard-json")
28+
.args(&input.extra_options)
29+
.stdin(Stdio::piped())
30+
.stdout(Stdio::piped())
31+
.stderr(Stdio::piped())
32+
.spawn()?;
33+
34+
let stdin_pipe = child.stdin.as_mut().expect("stdin must be piped");
35+
serde_json::to_writer(stdin_pipe, &input.input)?;
36+
37+
let json_in = serde_json::to_string_pretty(&input.input)?;
38+
39+
let output = child.wait_with_output()?;
40+
let stdout = output.stdout;
41+
let stderr = output.stderr;
42+
43+
if !output.status.success() {
44+
log::error!(
45+
"resolc failed exit={} stderr={} JSON-in={} ",
46+
output.status,
47+
String::from_utf8_lossy(&stderr),
48+
json_in,
49+
);
50+
}
51+
52+
let parsed: SolcStandardJsonOutput = serde_json::from_slice(&stdout).map_err(|e| {
53+
anyhow::anyhow!(
54+
"failed to parse resolc JSON output: {e}\nstderr: {}",
55+
String::from_utf8_lossy(&stderr)
56+
)
57+
})?;
58+
59+
Ok(CompilerOutput {
60+
input,
61+
output: parsed,
62+
})
63+
}
64+
65+
fn new(resolc_path: PathBuf) -> Self {
66+
Resolc { resolc_path }
67+
}
68+
69+
fn get_compiler_executable(
70+
config: &Arguments,
71+
_version: semver::Version,
72+
) -> anyhow::Result<PathBuf> {
73+
if !config.resolc.as_os_str().is_empty() {
74+
return Ok(config.resolc.clone());
75+
}
76+
77+
Ok(PathBuf::from("resolc"))
78+
}
79+
}

crates/compiler/src/solc.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use std::{
77
};
88

99
use crate::{CompilerInput, CompilerOutput, SolidityCompiler};
10+
use revive_dt_config::Arguments;
11+
use revive_dt_solc_binaries::download_solc;
1012

1113
pub struct Solc {
1214
solc_path: PathBuf,
@@ -39,4 +41,12 @@ impl SolidityCompiler for Solc {
3941
fn new(solc_path: PathBuf) -> Self {
4042
Self { solc_path }
4143
}
44+
45+
fn get_compiler_executable(
46+
config: &Arguments,
47+
version: semver::Version,
48+
) -> anyhow::Result<PathBuf> {
49+
let path = download_solc(config.directory(), version, config.wasm)?;
50+
Ok(path)
51+
}
4252
}

crates/core/src/driver/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use revive_dt_compiler::{Compiler, CompilerInput, SolidityCompiler};
88
use revive_dt_config::Arguments;
99
use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode};
1010
use revive_dt_node_interaction::EthereumNode;
11-
use revive_dt_solc_binaries::download_solc;
1211
use revive_solc_json_interface::SolcStandardJsonOutput;
1312

1413
use crate::Platform;
@@ -43,16 +42,18 @@ where
4342

4443
let sources = metadata.contract_sources()?;
4544
let base_path = metadata.directory()?.display().to_string();
45+
4646
let mut compiler = Compiler::<T::Compiler>::new().base_path(base_path.clone());
4747
for (file, _contract) in sources.values() {
4848
log::debug!("contract source {}", file.display());
4949
compiler = compiler.with_source(file)?;
5050
}
5151

52-
let solc_path = download_solc(self.config.directory(), version, self.config.wasm)?;
52+
let compiler_path = T::Compiler::get_compiler_executable(self.config, version)?;
53+
5354
let output = compiler
5455
.solc_optimizer(mode.solc_optimize())
55-
.try_build(solc_path)?;
56+
.try_build(compiler_path)?;
5657

5758
self.contracts.insert(output.input, output.output);
5859

crates/core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! This crate defines the testing configuration and
44
//! provides a helper utilty to execute tests.
55
6-
use revive_dt_compiler::{SolidityCompiler, solc};
6+
use revive_dt_compiler::{SolidityCompiler, revive_resolc, solc};
77
use revive_dt_node::geth;
88
use revive_dt_node_interaction::EthereumNode;
99

@@ -30,5 +30,5 @@ pub struct Kitchensink;
3030

3131
impl Platform for Kitchensink {
3232
type Blockchain = geth::Instance;
33-
type Compiler = solc::Solc;
33+
type Compiler = revive_resolc::Resolc;
3434
}

crates/core/src/main.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rayon::{ThreadPoolBuilder, prelude::*};
55

66
use revive_dt_config::*;
77
use revive_dt_core::{
8-
Geth,
8+
Geth, Kitchensink,
99
driver::{Driver, State},
1010
};
1111
use revive_dt_format::{corpus::Corpus, metadata::Metadata};
@@ -109,11 +109,16 @@ fn main_compile_only(
109109
) -> anyhow::Result<()> {
110110
tests.par_iter().for_each(|metadata| {
111111
for mode in &metadata.solc_modes() {
112-
let mut state = match platform {
113-
TestingPlatform::Geth => State::<Geth>::new(config),
114-
_ => todo!(),
112+
match platform {
113+
TestingPlatform::Geth => {
114+
let mut state = State::<Geth>::new(config);
115+
let _ = state.build_contracts(mode, metadata);
116+
}
117+
TestingPlatform::Kitchensink => {
118+
let mut state = State::<Kitchensink>::new(config);
119+
let _ = state.build_contracts(mode, metadata);
120+
}
115121
};
116-
let _ = state.build_contracts(mode, metadata);
117122
}
118123
});
119124

0 commit comments

Comments
 (0)