Skip to content

Commit 60a8f35

Browse files
MBerguerelfedyJrigada
authored
feat: Cache invalidation on zksolc version change (#871)
--------- Co-authored-by: elfedy <[email protected]> Co-authored-by: Jrigada <[email protected]>
1 parent 43c6159 commit 60a8f35

File tree

13 files changed

+183
-104
lines changed

13 files changed

+183
-104
lines changed

crates/common/src/compile.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ use foundry_compilers::{
2020
Artifact, Project, ProjectBuilder, ProjectCompileOutput, ProjectPathsConfig, SolcConfig,
2121
};
2222
use foundry_zksync_compilers::compilers::{
23-
artifact_output::zk::ZkArtifactOutput,
24-
zksolc::{ZkSolc, ZkSolcCompiler},
23+
artifact_output::zk::ZkArtifactOutput, zksolc::ZkSolcCompiler,
2524
};
2625

2726
use num_format::{Locale, ToFormattedString};
27+
2828
use std::{
2929
collections::BTreeMap,
3030
fmt::Display,
@@ -330,7 +330,7 @@ impl ProjectCompiler {
330330
let files = self.files.clone();
331331

332332
{
333-
let zksolc_version = ZkSolc::get_version_for_path(&project.compiler.zksolc)?;
333+
let zksolc_version = project.settings.zksolc_version_ref();
334334
Report::new(SpinnerReporter::spawn_with(format!("Using zksolc-{zksolc_version}")));
335335
}
336336
self.zksync_compile_with(|| {

crates/config/src/zksync.rs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ impl ZkSyncConfig {
114114
libraries: Libraries,
115115
evm_version: EvmVersion,
116116
via_ir: bool,
117-
) -> ZkSolcSettings {
117+
offline: bool,
118+
) -> Result<ZkSolcSettings, SolcError> {
118119
let optimizer = Optimizer {
119120
enabled: Some(self.optimizer),
120121
mode: Some(self.optimizer_mode),
@@ -124,7 +125,7 @@ impl ZkSyncConfig {
124125
jump_table_density_threshold: None,
125126
};
126127

127-
let zk_settings = ZkSettings {
128+
let settings = ZkSettings {
128129
libraries,
129130
optimizer,
130131
evm_version: Some(evm_version),
@@ -146,8 +147,22 @@ impl ZkSyncConfig {
146147
suppressed_errors: self.suppressed_errors.clone(),
147148
};
148149

150+
let zksolc_path = if let Some(path) = config_ensure_zksolc(self.zksolc.as_ref(), offline)? {
151+
path
152+
} else if !offline {
153+
let default_version = semver::Version::new(1, 5, 11);
154+
let mut zksolc = ZkSolc::find_installed_version(&default_version)?;
155+
if zksolc.is_none() {
156+
ZkSolc::blocking_install(&default_version)?;
157+
zksolc = ZkSolc::find_installed_version(&default_version)?;
158+
}
159+
zksolc.unwrap_or_else(|| panic!("Could not install zksolc v{default_version}"))
160+
} else {
161+
"zksolc".into()
162+
};
163+
149164
// `cli_settings` get set from `Project` values when building `ZkSolcVersionedInput`
150-
ZkSolcSettings { settings: zk_settings, cli_settings: CliSettings::default() }
165+
ZkSolcSettings::new_from_path(settings, CliSettings::default(), zksolc_path)
151166
}
152167
}
153168

@@ -163,34 +178,10 @@ pub fn config_zksolc_settings(config: &Config) -> Result<ZkSolcSettings, SolcErr
163178
Err(e) => return Err(SolcError::msg(format!("Failed to parse libraries: {e}"))),
164179
};
165180

166-
Ok(config.zksync.settings(libraries, config.evm_version, config.via_ir))
167-
}
168-
169-
/// Return the configured `zksolc` compiler
170-
///
171-
/// If not `offline`, will install the default version automatically
172-
/// Will fallback to `zksolc` present in the environment
173-
pub fn config_zksolc_compiler(config: &Config) -> Result<ZkSolcCompiler, SolcError> {
174-
let zksolc = if let Some(zksolc) =
175-
config_ensure_zksolc(config.zksync.zksolc.as_ref(), config.offline)?
176-
{
177-
zksolc
178-
} else if !config.offline {
179-
let default_version = semver::Version::new(1, 5, 11);
180-
let mut zksolc = ZkSolc::find_installed_version(&default_version)?;
181-
if zksolc.is_none() {
182-
ZkSolc::blocking_install(&default_version)?;
183-
zksolc = ZkSolc::find_installed_version(&default_version)?;
184-
}
185-
zksolc.unwrap_or_else(|| panic!("Could not install zksolc v{default_version}"))
186-
} else {
187-
"zksolc".into()
188-
};
189-
190-
Ok(ZkSolcCompiler { zksolc, solc: config_solc_compiler(config)? })
181+
config.zksync.settings(libraries, config.evm_version, config.via_ir, config.offline)
191182
}
192183

193-
/// Create a new zkSync project
184+
/// Create a new ZKsync project
194185
pub fn config_create_project(
195186
config: &Config,
196187
cached: bool,
@@ -217,7 +208,7 @@ pub fn config_create_project(
217208
builder = builder.sparse_output(filter);
218209
}
219210

220-
let zksolc_compiler = config_zksolc_compiler(config)?;
211+
let zksolc_compiler = ZkSolcCompiler { solc: config_solc_compiler(config)? };
221212

222213
let project = builder.build(zksolc_compiler)?;
223214

crates/linking/src/zksync.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub const DEPLOY_TIME_LINKING_ZKSOLC_MIN_VERSION: Version = Version::new(1, 5, 9
4444
#[derive(Debug)]
4545
pub struct ZkLinker<'a> {
4646
pub linker: Linker<'a>,
47-
pub compiler: ZkSolcCompiler,
47+
pub compiler: PathBuf,
4848
pub compiler_output: &'a ProjectCompileOutput<ZkSolcCompiler, ZkArtifactOutput>,
4949
}
5050

@@ -57,7 +57,7 @@ impl<'a> ZkLinker<'a> {
5757
pub fn new(
5858
root: impl Into<PathBuf>,
5959
contracts: ArtifactContracts<CompactContractBytecodeCow<'a>>,
60-
compiler: ZkSolcCompiler,
60+
compiler: PathBuf,
6161
compiler_output: &'a ProjectCompileOutput<ZkSolcCompiler, ZkArtifactOutput>,
6262
) -> Self {
6363
Self { linker: Linker::new(root, contracts), compiler, compiler_output }
@@ -299,7 +299,7 @@ impl<'a> ZkLinker<'a> {
299299
contracts: &ArtifactContracts<CompactContractBytecodeCow<'a>>,
300300
target: &ArtifactId,
301301
libraries: &Libraries,
302-
zksolc: &ZkSolcCompiler,
302+
zksolc_path: &Path,
303303
) -> Result<CompactContractBytecodeCow<'a>, ZkLinkerError> {
304304
let artifact_to_link_id = |id: &ArtifactId| format!("{}:{}", id.source.display(), id.name);
305305

@@ -336,7 +336,7 @@ impl<'a> ZkLinker<'a> {
336336
.collect::<HashSet<_>>();
337337

338338
let mut link_output =
339-
zk_link::zksolc_link(zksolc, zk_link::LinkJsonInput { bytecodes, libraries })
339+
zk_link::zksolc_link(zksolc_path, zk_link::LinkJsonInput { bytecodes, libraries })
340340
.expect("able to call zksolc --link"); // TODO(zk): proper error check
341341

342342
let link_id = &artifact_to_link_id(target);

crates/script/src/build/zksync.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,27 @@ use super::BuildData;
1818

1919
impl BuildData {
2020
fn get_zk_linker(&self, script_config: &ScriptConfig) -> Result<ZkLinker<'_>> {
21-
let zksolc = foundry_config::zksync::config_zksolc_compiler(&script_config.config)
21+
let zksolc_settings = foundry_config::zksync::config_zksolc_settings(&script_config.config)
2222
.context("retrieving zksolc compiler to be used for linking")?;
23-
let version = zksolc.version().context("trying to determine zksolc version")?;
23+
let version = zksolc_settings.zksolc_version_ref();
2424

2525
let Some(input) = self.zk_output.as_ref() else {
2626
eyre::bail!("unable to link zk artifacts if no zk compilation output is provided")
2727
};
2828

29-
let linker =
30-
ZkLinker::new(self.project_root.clone(), input.artifact_ids().collect(), zksolc, input);
29+
let linker = ZkLinker::new(
30+
self.project_root.clone(),
31+
input.artifact_ids().collect(),
32+
zksolc_settings.zksolc_path(),
33+
input,
34+
);
3135

3236
let mut libs = Default::default();
3337
linker.zk_collect_dependencies(&self.target, &mut libs, None)?;
3438

3539
// if there are no no libs, no linking will happen
3640
// so we can skip version check
37-
if !libs.is_empty() && version < DEPLOY_TIME_LINKING_ZKSOLC_MIN_VERSION {
41+
if !libs.is_empty() && version < &DEPLOY_TIME_LINKING_ZKSOLC_MIN_VERSION {
3842
eyre::bail!(
3943
"deploy-time linking not supported. minimum: {}, given: {}",
4044
DEPLOY_TIME_LINKING_ZKSOLC_MIN_VERSION,

crates/strategy/zksync/src/executor/runner/libraries.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ impl ZksyncExecutorStrategyRunner {
5656
let contracts: ArtifactContracts<CompactContractBytecodeCow<'_>> =
5757
input.artifact_ids().collect();
5858

59-
let Ok(zksolc) = foundry_config::zksync::config_zksolc_compiler(config) else {
59+
let Ok(zksolc_settings) = foundry_config::zksync::config_zksolc_settings(config) else {
6060
tracing::error!("unable to determine zksolc compiler to be used for linking");
6161
// TODO(zk): better error
6262
return Err(LinkerError::CyclicDependency);
6363
};
64-
let version = zksolc.version().map_err(|_| LinkerError::CyclicDependency)?;
64+
let version = zksolc_settings.zksolc_version_ref();
6565

66-
let linker = ZkLinker::new(root, contracts.clone(), zksolc, input);
66+
let linker = ZkLinker::new(root, contracts.clone(), zksolc_settings.zksolc_path(), input);
6767

6868
let zk_linker_error_to_linker = |zk_error| match zk_error {
6969
ZkLinkerError::Inner(err) => err,
@@ -93,7 +93,7 @@ impl ZksyncExecutorStrategyRunner {
9393
// so we can skip the version check
9494
if !libraries.is_empty() {
9595
// TODO(zk): better error
96-
if version < DEPLOY_TIME_LINKING_ZKSOLC_MIN_VERSION {
96+
if version < &DEPLOY_TIME_LINKING_ZKSOLC_MIN_VERSION {
9797
tracing::error!(
9898
%version,
9999
minimum_version = %DEPLOY_TIME_LINKING_ZKSOLC_MIN_VERSION,

crates/verify/src/etherscan/flatten.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ Diagnostics: {diags}",
188188
},
189189
solc_version: solc_version.clone(),
190190
cli_settings: CliSettings::default(),
191+
zksolc_path,
191192
};
192193

193194
let solc_compiler = if compiler_version.is_zksync_solc {
@@ -199,7 +200,7 @@ Diagnostics: {diags}",
199200
SolcCompiler::Specific(solc)
200201
};
201202

202-
let zksolc_compiler = ZkSolcCompiler { zksolc: zksolc_path, solc: solc_compiler };
203+
let zksolc_compiler = ZkSolcCompiler { solc: solc_compiler };
203204

204205
let out = zksolc_compiler.compile(&input)?;
205206
if out.errors.iter().any(|e| e.is_error()) {

crates/verify/src/zk_provider.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl ZkVerificationContext {
4545
let mut project =
4646
foundry_config::zksync::config_create_project(&config, config.cache, false)?;
4747
project.no_artifacts = true;
48-
let zksolc_version = ZkSolc::get_version_for_path(&project.compiler.zksolc)?;
48+
let zksolc_version = project.settings.zksolc_version_ref();
4949

5050
let (solc_version, is_zksync_solc) = if let Some(solc) = &config.zksync.solc_path {
5151
let solc_type_and_version = zksolc::get_solc_version_info(solc)?;
@@ -68,7 +68,7 @@ impl ZkVerificationContext {
6868
};
6969

7070
let compiler_version =
71-
ZkVersion { zksolc: zksolc_version, solc: solc_version, is_zksync_solc };
71+
ZkVersion { zksolc: zksolc_version.clone(), solc: solc_version, is_zksync_solc };
7272

7373
Ok(Self { config, project, target_name, target_path, compiler_version })
7474
}

crates/zksync/compilers/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,4 @@ similar-asserts.workspace = true
3737
fd-lock = "4.0.2"
3838
tempfile.workspace = true
3939
foundry-test-utils.workspace = true
40+

crates/zksync/compilers/src/compilers/zksolc/input.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ pub struct ZkSolcVersionedInput {
2525
pub solc_version: Version,
2626
/// zksolc cli settings
2727
pub cli_settings: solc::CliSettings,
28+
/// zksolc binary path
29+
pub zksolc_path: PathBuf,
2830
}
2931

3032
impl CompilerInput for ZkSolcVersionedInput {
@@ -40,10 +42,11 @@ impl CompilerInput for ZkSolcVersionedInput {
4042
language: Self::Language,
4143
version: Version,
4244
) -> Self {
43-
let ZkSolcSettings { settings, cli_settings } = settings;
45+
let zksolc_path = settings.zksolc_path();
46+
let ZkSolcSettings { settings, cli_settings, .. } = settings;
4447
let input = ZkSolcInput::new(language, sources, settings).sanitized(&version);
4548

46-
Self { solc_version: version, input, cli_settings }
49+
Self { solc_version: version, input, cli_settings, zksolc_path }
4750
}
4851

4952
fn language(&self) -> Self::Language {

crates/zksync/compilers/src/compilers/zksolc/mod.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,12 @@ impl ZkSolcOS {
121121
}
122122

123123
/// ZkSolc compiler
124-
#[derive(Debug, Clone)]
124+
#[derive(Debug, Clone, Default)]
125125
pub struct ZkSolcCompiler {
126-
/// zksolc path
127-
pub zksolc: PathBuf,
128126
/// solc compiler to use along zksolc
129127
pub solc: SolcCompiler,
130128
}
131129

132-
impl Default for ZkSolcCompiler {
133-
fn default() -> Self {
134-
let zksolc =
135-
ZkSolc::get_path_for_version(&ZKSOLC_VERSION).expect("Could not install zksolc");
136-
Self { zksolc, solc: Default::default() }
137-
}
138-
}
139-
140130
impl Compiler for ZkSolcCompiler {
141131
type Input = ZkSolcVersionedInput;
142132
type CompilationError = Error;
@@ -152,6 +142,7 @@ impl Compiler for ZkSolcCompiler {
152142
let zksolc = self.zksolc(input)?;
153143

154144
let mut zk_output = zksolc.compile(&input.input)?;
145+
155146
let mut metadata = BTreeMap::new();
156147
if let Some(solc_version) = zk_output.version.take() {
157148
metadata.insert("solcVersion".to_string(), solc_version.into());
@@ -236,19 +227,14 @@ impl ZkSolcCompiler {
236227
}
237228
};
238229

239-
let mut zksolc = ZkSolc::new(self.zksolc.clone(), solc)?;
230+
let mut zksolc = ZkSolc::new(input.zksolc_path.clone(), solc)?;
240231

241232
zksolc.base_path.clone_from(&input.cli_settings.base_path);
242233
zksolc.allow_paths.clone_from(&input.cli_settings.allow_paths);
243234
zksolc.include_paths.clone_from(&input.cli_settings.include_paths);
244235

245236
Ok(zksolc)
246237
}
247-
248-
/// Retrieve the version of the specified `zksolc`
249-
pub fn version(&self) -> Result<Version> {
250-
ZkSolc::get_version_for_path(self.zksolc.as_ref())
251-
}
252238
}
253239

254240
/// Version metadata. Will include `zksync_version` if compiler is zksync solc.

0 commit comments

Comments
 (0)