From f2d29fcc63222dc414fa8b6b6e6fa9fff1c7e654 Mon Sep 17 00:00:00 2001 From: rahulbarman Date: Sat, 9 May 2026 02:41:42 +0530 Subject: [PATCH 1/3] fix: auto-pull latest Nethermind version in EL test --- .../src/build_utils.rs | 92 +++++++++++++++++++ .../src/nethermind.rs | 8 +- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/testing/execution_engine_integration/src/build_utils.rs b/testing/execution_engine_integration/src/build_utils.rs index 5d965206604..c6c71d763f6 100644 --- a/testing/execution_engine_integration/src/build_utils.rs +++ b/testing/execution_engine_integration/src/build_utils.rs @@ -88,6 +88,49 @@ pub fn get_latest_release(repo_dir: &Path, branch_name: &str) -> Result Result { + // If the directory was already present it is possible we don't have the most recent tags. + // Fetch them + output_to_result( + Command::new("git") + .arg("fetch") + .arg("--tags") + .arg("--force") + .current_dir(repo_dir) + .output() + .map_err(|e| format!("Failed to fetch tags for {repo_dir:?}: Err: {e}"))?, + |_| {}, + )?; + let tags = output_to_result( + Command::new("git") + .arg("tag") + .arg("--list") + .arg("--sort=-v:refname") + .current_dir(repo_dir) + .output() + .map_err(|e| format!("Failed to list tags for {repo_dir:?}: Err: {e}"))?, + |stdout| String::from_utf8_lossy(&stdout).into_owned(), + )?; + tags.lines() + .map(str::trim) + .find(|tag| is_stable_semver(tag)) + .map(str::to_string) + .ok_or_else(|| format!("No stable release tag found in {repo_dir:?}")) +} + +/// Returns `true` if `tag` looks like a stable `MAJOR.MINOR.PATCH` version. +fn is_stable_semver(tag: &str) -> bool { + let parts: Vec<&str> = tag.split('.').collect(); + parts.len() == 3 + && parts + .iter() + .all(|p| !p.is_empty() && p.chars().all(|c| c.is_ascii_digit())) +} + #[allow(dead_code)] pub fn update_branch(repo_dir: &Path, branch_name: &str) -> Result<(), String> { output_to_result( @@ -136,3 +179,52 @@ pub fn build_stdio() -> Stdio { Stdio::inherit() } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_is_stable_semver_accepts_valid() { + assert!(is_stable_semver("1.37.2")); + assert!(is_stable_semver("0.0.0")); + assert!(is_stable_semver("1.0.0")); + assert!(is_stable_semver("10.20.30")); + assert!(is_stable_semver("100.200.300")); + } + + #[test] + fn test_is_stable_semver_rejects_prerelease() { + assert!(!is_stable_semver("1.37.0-rc")); + assert!(!is_stable_semver("1.37.0-rc1")); + assert!(!is_stable_semver("1.37.0-alpha")); + assert!(!is_stable_semver("1.37.0-beta")); + assert!(!is_stable_semver("1.37.0-unstable")); + } + + #[test] + fn test_is_stable_semver_rejects_wrong_arity() { + assert!(!is_stable_semver("")); + assert!(!is_stable_semver("1")); + assert!(!is_stable_semver("1.0")); + assert!(!is_stable_semver("1.0.0.0")); + assert!(!is_stable_semver("1.35.2.1")); + } + + #[test] + fn test_is_stable_semver_rejects_non_numeric() { + assert!(!is_stable_semver("v1.0.0")); + assert!(!is_stable_semver("1.a.0")); + assert!(!is_stable_semver("abc")); + assert!(!is_stable_semver("1..0")); + assert!(!is_stable_semver(".1.0")); + assert!(!is_stable_semver("1.0.")); + } + + #[test] + fn test_is_stable_semver_rejects_whitespace() { + assert!(!is_stable_semver(" 1.0.0")); + assert!(!is_stable_semver("1.0.0 ")); + assert!(!is_stable_semver("1. 0.0")); + } +} diff --git a/testing/execution_engine_integration/src/nethermind.rs b/testing/execution_engine_integration/src/nethermind.rs index e606f5558c3..2341795f1ce 100644 --- a/testing/execution_engine_integration/src/nethermind.rs +++ b/testing/execution_engine_integration/src/nethermind.rs @@ -8,10 +8,6 @@ use std::path::{Path, PathBuf}; use std::process::{Child, Command, Output}; use tempfile::TempDir; -/// We've pinned the Nethermind version since our method of using the `master` branch to -/// find the latest tag isn't working. It appears Nethermind don't always tag on `master`. -/// We should fix this so we always pull the latest version of Nethermind. -const NETHERMIND_BRANCH: &str = "release/1.27.0"; const NETHERMIND_REPO_URL: &str = "https://github.com/NethermindEth/nethermind"; fn build_result(repo_dir: &Path) -> Output { @@ -34,8 +30,8 @@ pub fn build(execution_clients_dir: &Path) { build_utils::clone_repo(execution_clients_dir, NETHERMIND_REPO_URL).unwrap() } - // Get the latest tag - let last_release = build_utils::get_latest_release(&repo_dir, NETHERMIND_BRANCH).unwrap(); + // Get the latest stable release tag + let last_release = build_utils::get_latest_stable_release(&repo_dir).unwrap(); build_utils::checkout(&repo_dir, dbg!(&last_release)).unwrap(); // Build nethermind From fa7da7c858374c625789893bd33810ddcdaf4162 Mon Sep 17 00:00:00 2001 From: rahulbarman Date: Mon, 11 May 2026 19:46:40 +0530 Subject: [PATCH 2/3] fix: use .slnx solution file (Nethermind migrated from .sln) --- testing/execution_engine_integration/src/nethermind.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/execution_engine_integration/src/nethermind.rs b/testing/execution_engine_integration/src/nethermind.rs index 2341795f1ce..5999b47e15a 100644 --- a/testing/execution_engine_integration/src/nethermind.rs +++ b/testing/execution_engine_integration/src/nethermind.rs @@ -13,7 +13,7 @@ const NETHERMIND_REPO_URL: &str = "https://github.com/NethermindEth/nethermind"; fn build_result(repo_dir: &Path) -> Output { Command::new("dotnet") .arg("build") - .arg("src/Nethermind/Nethermind.sln") + .arg("src/Nethermind/Nethermind.slnx") .arg("-c") .arg("Release") .arg("-p:TreatWarningsAsErrors=false") From 3c14e5329d208144ae54eaffcbea7c2d36b77bb9 Mon Sep 17 00:00:00 2001 From: rahulbarman Date: Thu, 14 May 2026 04:18:31 +0530 Subject: [PATCH 3/3] fix: update Nethermind integration for latest releases --- .../src/genesis_json.rs | 2 +- .../src/nethermind.rs | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/testing/execution_engine_integration/src/genesis_json.rs b/testing/execution_engine_integration/src/genesis_json.rs index e5bf90d41f8..dfcc878c2f9 100644 --- a/testing/execution_engine_integration/src/genesis_json.rs +++ b/testing/execution_engine_integration/src/genesis_json.rs @@ -124,7 +124,7 @@ pub fn nethermind_genesis_json() -> Value { "timestamp": "0x63585F88", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "extraData": "", - "gasLimit": "0x400000" + "gasLimit": "0x1C9C380" }, "accounts": { "0x7b8C3a386C0eea54693fFB0DA17373ffC9228139": { diff --git a/testing/execution_engine_integration/src/nethermind.rs b/testing/execution_engine_integration/src/nethermind.rs index 5999b47e15a..670a4f62ddc 100644 --- a/testing/execution_engine_integration/src/nethermind.rs +++ b/testing/execution_engine_integration/src/nethermind.rs @@ -13,7 +13,7 @@ const NETHERMIND_REPO_URL: &str = "https://github.com/NethermindEth/nethermind"; fn build_result(repo_dir: &Path) -> Output { Command::new("dotnet") .arg("build") - .arg("src/Nethermind/Nethermind.slnx") + .arg("src/Nethermind/Nethermind.Runner/Nethermind.Runner.csproj") .arg("-c") .arg("Release") .arg("-p:TreatWarningsAsErrors=false") @@ -62,7 +62,7 @@ pub struct NethermindEngine; impl NethermindEngine { fn binary_path() -> PathBuf { let manifest_dir: PathBuf = env::var("CARGO_MANIFEST_DIR").unwrap().into(); - manifest_dir + let nethermind_dir = manifest_dir .join("execution_clients") .join("nethermind") .join("src") @@ -70,8 +70,14 @@ impl NethermindEngine { .join("artifacts") .join("bin") .join("Nethermind.Runner") - .join("release") - .join("nethermind") + .join("release"); + + let latest_path = nethermind_dir.join("net10.0").join("nethermind"); + if latest_path.exists() { + latest_path + } else { + nethermind_dir.join("nethermind") + } } } @@ -98,7 +104,7 @@ impl GenericExecutionEngine for NethermindEngine { .arg("--datadir") .arg(datadir.path().to_str().unwrap()) .arg("--config") - .arg("hive") + .arg("none.json") .arg("--Init.ChainSpecPath") .arg(genesis_json_path.to_str().unwrap()) .arg("--Merge.TerminalTotalDifficulty")