From dbe90dbe966dc46ef6c1d83e2a33155ea6168ef0 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:05:05 -0700 Subject: [PATCH] remove lighthouse_version from all library crate deps Thread version strings from top-level binaries into library crates via config structs and Context objects. This eliminates cargo cache invalidation on every git commit caused by git_version!() macro. lighthouse_version now only appears as a [dependency] in the lighthouse and lcli binaries, and as a [dev-dependency] in beacon_chain (for test assertions). --- Cargo.lock | 9 ---- beacon_node/beacon_chain/Cargo.toml | 2 +- beacon_node/beacon_chain/src/builder.rs | 9 ++++ .../beacon_chain/src/graffiti_calculator.rs | 30 +++++++----- beacon_node/builder_client/Cargo.toml | 1 - beacon_node/builder_client/src/lib.rs | 2 +- beacon_node/client/src/builder.rs | 19 +++++++- beacon_node/client/src/config.rs | 12 +++++ beacon_node/execution_layer/Cargo.toml | 1 - .../execution_layer/src/engine_api/http.rs | 46 +++++++++++-------- beacon_node/execution_layer/src/lib.rs | 24 ++++++++-- beacon_node/http_api/Cargo.toml | 1 - beacon_node/http_api/src/lib.rs | 21 ++++++--- beacon_node/http_api/src/test_utils.rs | 1 + beacon_node/http_api/tests/tests.rs | 2 +- beacon_node/http_metrics/Cargo.toml | 1 - beacon_node/http_metrics/src/lib.rs | 5 +- beacon_node/http_metrics/tests/tests.rs | 1 + beacon_node/lighthouse_network/Cargo.toml | 1 - beacon_node/lighthouse_network/src/config.rs | 12 ++++- .../lighthouse_network/src/discovery/enr.rs | 7 ++- .../lighthouse_network/src/service/mod.rs | 2 +- common/monitoring_api/Cargo.toml | 2 - common/monitoring_api/src/types.rs | 8 ++-- lighthouse/src/main.rs | 17 ++++++- validator_client/http_api/Cargo.toml | 1 - validator_client/http_api/src/lib.rs | 21 +++++---- validator_client/http_api/src/test_utils.rs | 3 +- validator_client/http_api/src/tests.rs | 3 +- validator_client/http_metrics/Cargo.toml | 1 - validator_client/http_metrics/src/lib.rs | 5 +- validator_client/src/config.rs | 4 ++ validator_client/src/lib.rs | 2 + 33 files changed, 187 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ed7bfd0b60..5c45dbb7eb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1601,7 +1601,6 @@ dependencies = [ "context_deserialize", "eth2", "ethereum_ssz", - "lighthouse_version", "mockito", "reqwest", "sensitive_url", @@ -3412,7 +3411,6 @@ dependencies = [ "jsonwebtoken", "keccak-hash", "kzg", - "lighthouse_version", "logging", "lru 0.12.5", "metrics", @@ -4259,7 +4257,6 @@ dependencies = [ "hex", "lighthouse_network", "lighthouse_tracing", - "lighthouse_version", "logging", "lru 0.12.5", "metrics", @@ -4295,7 +4292,6 @@ dependencies = [ "beacon_chain", "health_metrics", "lighthouse_network", - "lighthouse_version", "logging", "malloc_utils", "metrics", @@ -5527,7 +5523,6 @@ dependencies = [ "libp2p", "libp2p-gossipsub", "libp2p-mplex", - "lighthouse_version", "local-ip-address", "logging", "lru 0.12.5", @@ -6038,9 +6033,7 @@ version = "0.1.0" dependencies = [ "eth2", "health_metrics", - "lighthouse_version", "metrics", - "regex", "reqwest", "sensitive_url", "serde", @@ -9804,7 +9797,6 @@ dependencies = [ "initialized_validators", "itertools 0.10.5", "lighthouse_validator_store", - "lighthouse_version", "logging", "parking_lot", "rand 0.9.2", @@ -9839,7 +9831,6 @@ version = "0.1.0" dependencies = [ "health_metrics", "lighthouse_validator_store", - "lighthouse_version", "logging", "malloc_utils", "metrics", diff --git a/beacon_node/beacon_chain/Cargo.toml b/beacon_node/beacon_chain/Cargo.toml index 734cfdf32bb..59d417560fe 100644 --- a/beacon_node/beacon_chain/Cargo.toml +++ b/beacon_node/beacon_chain/Cargo.toml @@ -35,7 +35,6 @@ int_to_bytes = { workspace = true } itertools = { workspace = true } kzg = { workspace = true } lighthouse_tracing = { workspace = true } -lighthouse_version = { workspace = true } logging = { workspace = true } lru = { workspace = true } merkle_proof = { workspace = true } @@ -73,6 +72,7 @@ zstd = { workspace = true } [dev-dependencies] criterion = { workspace = true } +lighthouse_version = { workspace = true } maplit = { workspace = true } mockall = { workspace = true } mockall_double = { workspace = true } diff --git a/beacon_node/beacon_chain/src/builder.rs b/beacon_node/beacon_chain/src/builder.rs index 58dbf1c35e8..d3a1e6b29fd 100644 --- a/beacon_node/beacon_chain/src/builder.rs +++ b/beacon_node/beacon_chain/src/builder.rs @@ -97,6 +97,7 @@ pub struct BeaconChainBuilder { spec: Arc, chain_config: ChainConfig, beacon_graffiti: GraffitiOrigin, + commit_prefix: String, slasher: Option>>, // Pending I/O batch that is constructed during building and should be executed atomically // alongside `PersistedBeaconChain` storage when `BeaconChainBuilder::build` is called. @@ -139,6 +140,7 @@ where spec: Arc::new(E::default_spec()), chain_config: ChainConfig::default(), beacon_graffiti: GraffitiOrigin::default(), + commit_prefix: String::new(), slasher: None, pending_io_batch: vec![], kzg, @@ -709,6 +711,12 @@ where self } + /// Sets the `commit_prefix` field used by the graffiti calculator. + pub fn commit_prefix(mut self, commit_prefix: String) -> Self { + self.commit_prefix = commit_prefix; + self + } + /// Sets the `ChainConfig` that determines `BeaconChain` runtime behaviour. pub fn chain_config(mut self, config: ChainConfig) -> Self { self.chain_config = config; @@ -1040,6 +1048,7 @@ where self.beacon_graffiti, self.execution_layer, slot_clock.slot_duration() * E::slots_per_epoch() as u32, + self.commit_prefix, ), slasher: self.slasher.clone(), validator_monitor: RwLock::new(validator_monitor), diff --git a/beacon_node/beacon_chain/src/graffiti_calculator.rs b/beacon_node/beacon_chain/src/graffiti_calculator.rs index 85470715c9f..051a098b68d 100644 --- a/beacon_node/beacon_chain/src/graffiti_calculator.rs +++ b/beacon_node/beacon_chain/src/graffiti_calculator.rs @@ -35,7 +35,13 @@ impl GraffitiOrigin { impl Default for GraffitiOrigin { fn default() -> Self { - let version_bytes = lighthouse_version::VERSION.as_bytes(); + Self::from_version(concat!("Lighthouse/v", env!("CARGO_PKG_VERSION"))) + } +} + +impl GraffitiOrigin { + pub fn from_version(version: &str) -> Self { + let version_bytes = version.as_bytes(); let trimmed_len = std::cmp::min(version_bytes.len(), GRAFFITI_BYTES_LEN); let mut bytes = [0u8; GRAFFITI_BYTES_LEN]; bytes[..trimmed_len].copy_from_slice(&version_bytes[..trimmed_len]); @@ -72,6 +78,7 @@ pub struct GraffitiCalculator { pub beacon_graffiti: GraffitiOrigin, execution_layer: Option>, pub epoch_duration: Duration, + commit_prefix: String, } impl GraffitiCalculator { @@ -79,11 +86,13 @@ impl GraffitiCalculator { beacon_graffiti: GraffitiOrigin, execution_layer: Option>, epoch_duration: Duration, + commit_prefix: String, ) -> Self { Self { beacon_graffiti, execution_layer, epoch_duration, + commit_prefix, } } @@ -150,16 +159,15 @@ impl GraffitiCalculator { return default_graffiti; } - let lighthouse_commit_prefix = - CommitPrefix::try_from(lighthouse_version::COMMIT_PREFIX.to_string()) - .unwrap_or_else(|error_message| { - // This really shouldn't happen but we want to definitly log if it does - crit!( - error = error_message, - "Failed to parse lighthouse commit prefix" - ); - CommitPrefix("00000000".to_string()) - }); + let lighthouse_commit_prefix = CommitPrefix::try_from(self.commit_prefix.clone()) + .unwrap_or_else(|error_message| { + // This really shouldn't happen but we want to definitly log if it does + crit!( + error = error_message, + "Failed to parse lighthouse commit prefix" + ); + CommitPrefix("00000000".to_string()) + }); engine_version.calculate_graffiti(lighthouse_commit_prefix, validator_graffiti) } diff --git a/beacon_node/builder_client/Cargo.toml b/beacon_node/builder_client/Cargo.toml index 09bf3f48b4e..48c0fe330d6 100644 --- a/beacon_node/builder_client/Cargo.toml +++ b/beacon_node/builder_client/Cargo.toml @@ -9,7 +9,6 @@ bls = { workspace = true } context_deserialize = { workspace = true } eth2 = { workspace = true } ethereum_ssz = { workspace = true } -lighthouse_version = { workspace = true } reqwest = { workspace = true } sensitive_url = { workspace = true } serde = { workspace = true } diff --git a/beacon_node/builder_client/src/lib.rs b/beacon_node/builder_client/src/lib.rs index 4fc6b3a379b..925806178ca 100644 --- a/beacon_node/builder_client/src/lib.rs +++ b/beacon_node/builder_client/src/lib.rs @@ -29,7 +29,7 @@ pub const DEFAULT_TIMEOUT_MILLIS: u64 = 15000; pub const DEFAULT_GET_HEADER_TIMEOUT_MILLIS: u64 = 1000; /// Default user agent for HTTP requests. -pub const DEFAULT_USER_AGENT: &str = lighthouse_version::VERSION; +pub const DEFAULT_USER_AGENT: &str = concat!("Lighthouse/v", env!("CARGO_PKG_VERSION")); /// The value we set on the `ACCEPT` http header to indicate a preference for ssz response. pub const PREFERENCE_ACCEPT_VALUE: &str = "application/octet-stream;q=1.0,application/json;q=0.9"; diff --git a/beacon_node/client/src/builder.rs b/beacon_node/client/src/builder.rs index c48021e45d4..f6c476bce9a 100644 --- a/beacon_node/client/src/builder.rs +++ b/beacon_node/client/src/builder.rs @@ -6,7 +6,9 @@ use crate::config::{ClientGenesis, Config as ClientConfig}; use crate::notifier::spawn_notifier; use beacon_chain::attestation_simulator::start_attestation_simulator_service; use beacon_chain::data_availability_checker::start_availability_cache_maintenance_service; -use beacon_chain::graffiti_calculator::start_engine_version_cache_refresh_service; +use beacon_chain::graffiti_calculator::{ + GraffitiOrigin, start_engine_version_cache_refresh_service, +}; use beacon_chain::proposer_prep_service::start_proposer_prep_service; use beacon_chain::schema_change::migrate_schema; use beacon_chain::{ @@ -90,6 +92,7 @@ pub struct ClientBuilder { beacon_processor_channels: Option>, light_client_server_rv: Option>>, eth_spec_instance: T::EthSpec, + version_with_platform: String, } impl @@ -123,6 +126,7 @@ where beacon_processor_config: None, beacon_processor_channels: None, light_client_server_rv: None, + version_with_platform: String::new(), } } @@ -158,12 +162,20 @@ where config: ClientConfig, node_id: [u8; 32], ) -> Result { + self.version_with_platform = config.version_with_platform.clone(); + let store = self.store.clone(); let chain_spec = self.chain_spec.clone(); let runtime_context = self.runtime_context.clone(); let eth_spec_instance = self.eth_spec_instance.clone(); let chain_config = config.chain.clone(); - let beacon_graffiti = config.beacon_graffiti; + let beacon_graffiti = if matches!(config.beacon_graffiti, GraffitiOrigin::Calculated(_)) + && !config.version.is_empty() + { + GraffitiOrigin::from_version(&config.version) + } else { + config.beacon_graffiti + }; let store = store.ok_or("beacon_chain_start_method requires a store")?; let runtime_context = @@ -208,6 +220,7 @@ where ) .chain_config(chain_config) .beacon_graffiti(beacon_graffiti) + .commit_prefix(config.commit_prefix.clone()) .event_handler(event_handler) .execution_layer(execution_layer) .node_custody_type(config.chain.node_custody_type) @@ -639,6 +652,7 @@ where network_globals: self.network_globals.clone(), beacon_processor_send: Some(beacon_processor_channels.beacon_processor_tx.clone()), sse_logging_components: runtime_context.sse_logging_components.clone(), + version: self.version_with_platform.clone(), }); let exit = runtime_context.executor.exit(); @@ -669,6 +683,7 @@ where db_path: self.db_path.clone(), freezer_db_path: self.freezer_db_path.clone(), gossipsub_registry: self.libp2p_registry.take().map(std::sync::Mutex::new), + version: self.version_with_platform.clone(), }); let exit = runtime_context.executor.exit(); diff --git a/beacon_node/client/src/config.rs b/beacon_node/client/src/config.rs index aeaa196df86..c58783314c2 100644 --- a/beacon_node/client/src/config.rs +++ b/beacon_node/client/src/config.rs @@ -51,6 +51,15 @@ pub enum ClientGenesis { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Config { data_dir: PathBuf, + /// Version string (e.g. "Lighthouse/v5.0.0-abc12345/x86_64-linux"). Set by the binary. + #[serde(skip)] + pub version: String, + /// Version with platform info for identifying this node in HTTP headers. + #[serde(skip)] + pub version_with_platform: String, + /// First 8 chars of the git commit hash. + #[serde(skip)] + pub commit_prefix: String, /// Name of the directory inside the data directory where the main "hot" DB is located. pub db_name: String, /// Path where the freezer database will be located. @@ -85,6 +94,9 @@ impl Default for Config { fn default() -> Self { Self { data_dir: PathBuf::from(DEFAULT_ROOT_DIR), + version: String::new(), + version_with_platform: String::new(), + commit_prefix: String::new(), db_name: "chain_db".to_string(), freezer_db_path: None, blobs_db_path: None, diff --git a/beacon_node/execution_layer/Cargo.toml b/beacon_node/execution_layer/Cargo.toml index c443e945743..4ac7ca01f55 100644 --- a/beacon_node/execution_layer/Cargo.toml +++ b/beacon_node/execution_layer/Cargo.toml @@ -24,7 +24,6 @@ hex = { workspace = true } jsonwebtoken = "9" keccak-hash = "0.10.0" kzg = { workspace = true } -lighthouse_version = { workspace = true } logging = { workspace = true } lru = { workspace = true } metrics = { workspace = true } diff --git a/beacon_node/execution_layer/src/engine_api/http.rs b/beacon_node/execution_layer/src/engine_api/http.rs index c421491f808..ea8ff9dc3ce 100644 --- a/beacon_node/execution_layer/src/engine_api/http.rs +++ b/beacon_node/execution_layer/src/engine_api/http.rs @@ -3,13 +3,11 @@ use super::*; use crate::auth::Auth; use crate::json_structures::*; -use lighthouse_version::{COMMIT_PREFIX, VERSION}; use reqwest::header::CONTENT_TYPE; use sensitive_url::SensitiveUrl; use serde::de::DeserializeOwned; use serde_json::json; use std::collections::HashSet; -use std::sync::LazyLock; use tokio::sync::Mutex; use std::time::{Duration, Instant}; @@ -89,18 +87,6 @@ pub static LIGHTHOUSE_CAPABILITIES: &[&str] = &[ ENGINE_GET_BLOBS_V2, ]; -/// We opt to initialize the JsonClientVersionV1 rather than the ClientVersionV1 -/// for two reasons: -/// 1. This saves the overhead of converting into Json for every engine call -/// 2. The Json version lacks error checking so we can avoid calling `unwrap()` -pub static LIGHTHOUSE_JSON_CLIENT_VERSION: LazyLock = - LazyLock::new(|| JsonClientVersionV1 { - code: ClientCode::Lighthouse.to_string(), - name: "Lighthouse".to_string(), - version: VERSION.replace("Lighthouse/", ""), - commit: COMMIT_PREFIX.to_string(), - }); - /// Contains methods to convert arbitrary bytes to an ETH2 deposit contract object. pub mod deposit_log { use bls::{PublicKeyBytes, SignatureBytes}; @@ -605,6 +591,7 @@ pub struct HttpJsonRpc { pub execution_timeout_multiplier: u32, pub engine_capabilities_cache: Mutex>>, pub engine_version_cache: Mutex>>>, + pub client_version: JsonClientVersionV1, auth: Option, } @@ -612,6 +599,7 @@ impl HttpJsonRpc { pub fn new( url: SensitiveUrl, execution_timeout_multiplier: Option, + client_version: JsonClientVersionV1, ) -> Result { Ok(Self { client: Client::builder().build()?, @@ -619,6 +607,7 @@ impl HttpJsonRpc { execution_timeout_multiplier: execution_timeout_multiplier.unwrap_or(1), engine_capabilities_cache: Mutex::new(None), engine_version_cache: Mutex::new(None), + client_version, auth: None, }) } @@ -627,6 +616,7 @@ impl HttpJsonRpc { url: SensitiveUrl, auth: Auth, execution_timeout_multiplier: Option, + client_version: JsonClientVersionV1, ) -> Result { Ok(Self { client: Client::builder().build()?, @@ -634,6 +624,7 @@ impl HttpJsonRpc { execution_timeout_multiplier: execution_timeout_multiplier.unwrap_or(1), engine_capabilities_cache: Mutex::new(None), engine_version_cache: Mutex::new(None), + client_version, auth: Some(auth), }) } @@ -1252,7 +1243,7 @@ impl HttpJsonRpc { /// `get_engine_version(Some(Duration::ZERO))` if you want to force /// fetching from the EE as this will cache the result. pub async fn get_client_version_v1(&self) -> Result, Error> { - let params = json!([*LIGHTHOUSE_JSON_CLIENT_VERSION]); + let params = json!([self.client_version]); let response: Vec = self .rpc_request( @@ -1488,19 +1479,36 @@ mod test { let rpc_url = SensitiveUrl::parse(&server.url()).unwrap(); let echo_url = SensitiveUrl::parse(&format!("{}/echo", server.url())).unwrap(); // Create rpc clients that include JWT auth headers if `with_auth` is true. + let test_client_version = JsonClientVersionV1 { + code: ClientCode::Lighthouse.to_string(), + name: "Lighthouse".to_string(), + version: "test".to_string(), + commit: "00000000".to_string(), + }; let (rpc_client, echo_client) = if with_auth { let rpc_auth = Auth::new(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap(), None, None); let echo_auth = Auth::new(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap(), None, None); ( - Arc::new(HttpJsonRpc::new_with_auth(rpc_url, rpc_auth, None).unwrap()), - Arc::new(HttpJsonRpc::new_with_auth(echo_url, echo_auth, None).unwrap()), + Arc::new( + HttpJsonRpc::new_with_auth( + rpc_url, + rpc_auth, + None, + test_client_version.clone(), + ) + .unwrap(), + ), + Arc::new( + HttpJsonRpc::new_with_auth(echo_url, echo_auth, None, test_client_version) + .unwrap(), + ), ) } else { ( - Arc::new(HttpJsonRpc::new(rpc_url, None).unwrap()), - Arc::new(HttpJsonRpc::new(echo_url, None).unwrap()), + Arc::new(HttpJsonRpc::new(rpc_url, None, test_client_version.clone()).unwrap()), + Arc::new(HttpJsonRpc::new(echo_url, None, test_client_version).unwrap()), ) }; diff --git a/beacon_node/execution_layer/src/lib.rs b/beacon_node/execution_layer/src/lib.rs index 554668dd8a7..a059febfd20 100644 --- a/beacon_node/execution_layer/src/lib.rs +++ b/beacon_node/execution_layer/src/lib.rs @@ -4,7 +4,7 @@ //! This crate only provides useful functionality for "The Merge", it does not provide any of the //! deposit-contract functionality that the `beacon_node/eth1` crate already provides. -use crate::json_structures::{BlobAndProofV1, BlobAndProofV2}; +use crate::json_structures::{BlobAndProofV1, BlobAndProofV2, JsonClientVersionV1}; use crate::payload_cache::PayloadCache; use arc_swap::ArcSwapOption; use auth::{Auth, JwtKey, strip_prefix}; @@ -467,6 +467,10 @@ pub struct Config { /// Default directory for the jwt secret if not provided through cli. pub default_datadir: PathBuf, pub execution_timeout_multiplier: Option, + /// Version string for identifying this CL client to the EL (e.g. "Lighthouse/v8.0.0-67da032"). + pub version: String, + /// First 8 chars of the git commit hash. + pub commit_prefix: String, } /// Provides access to one execution engine and provides a neat interface for consumption by the @@ -491,8 +495,17 @@ impl ExecutionLayer { jwt_version, default_datadir, execution_timeout_multiplier, + version, + commit_prefix, } = config; + let client_version = JsonClientVersionV1 { + code: ClientCode::Lighthouse.to_string(), + name: "Lighthouse".to_string(), + version: version.replace("Lighthouse/", ""), + commit: commit_prefix, + }; + let execution_url = url.ok_or(Error::NoEngine)?; // Use the default jwt secret path if not provided via cli. @@ -530,8 +543,13 @@ impl ExecutionLayer { let engine: Engine = { let auth = Auth::new(jwt_key, jwt_id, jwt_version); debug!(endpoint = %execution_url, jwt_path = ?secret_file.as_path(),"Loaded execution endpoint"); - let api = HttpJsonRpc::new_with_auth(execution_url, auth, execution_timeout_multiplier) - .map_err(Error::ApiError)?; + let api = HttpJsonRpc::new_with_auth( + execution_url, + auth, + execution_timeout_multiplier, + client_version, + ) + .map_err(Error::ApiError)?; Engine::new(api, executor.clone()) }; diff --git a/beacon_node/http_api/Cargo.toml b/beacon_node/http_api/Cargo.toml index 571dab10273..e638b759d5e 100644 --- a/beacon_node/http_api/Cargo.toml +++ b/beacon_node/http_api/Cargo.toml @@ -24,7 +24,6 @@ health_metrics = { workspace = true } hex = { workspace = true } lighthouse_network = { workspace = true } lighthouse_tracing = { workspace = true } -lighthouse_version = { workspace = true } logging = { workspace = true } lru = { workspace = true } metrics = { workspace = true } diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index 58cd2a3bdbc..785bb975f3f 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -61,7 +61,6 @@ use health_metrics::observe::Observe; use lighthouse_network::Enr; use lighthouse_network::NetworkGlobals; use lighthouse_network::PeerId; -use lighthouse_version::version_with_platform; use logging::{SSELoggingComponents, crit}; use network::{NetworkMessage, NetworkSenders}; use network_utils::enr_ext::EnrExt; @@ -128,6 +127,7 @@ pub struct Context { pub network_globals: Option>>, pub beacon_processor_send: Option>, pub sse_logging_components: Option, + pub version: String, } /// Configuration for the HTTP server. @@ -330,6 +330,7 @@ pub fn serve( shutdown: impl Future + Send + Sync + 'static, ) -> Result { let config = ctx.config.clone(); + let version = ctx.version.clone(); // Configure CORS. let cors_builder = { @@ -2141,11 +2142,17 @@ pub fn serve( .and(warp::path("version")) .and(warp::path::end()) // Bypass the `task_spawner` since this method returns a static string. - .then(|| async { - warp::reply::json(&api_types::GenericResponse::from(api_types::VersionData { - version: version_with_platform(), - })) - .into_response() + .then({ + let version = version.clone(); + move || { + let version = version.clone(); + async move { + warp::reply::json(&api_types::GenericResponse::from(api_types::VersionData { + version, + })) + .into_response() + } + } }); // GET node/syncing @@ -3387,7 +3394,7 @@ pub fn serve( .with(tracing_logging()) .with(prometheus_metrics()) // Add a `Server` header. - .map(|reply| warp::reply::with_header(reply, "Server", &version_with_platform())) + .map(move |reply| warp::reply::with_header(reply, "Server", &version)) .with(cors_builder.build()) .boxed(); diff --git a/beacon_node/http_api/src/test_utils.rs b/beacon_node/http_api/src/test_utils.rs index 27e2a27d35c..49344f6e9d3 100644 --- a/beacon_node/http_api/src/test_utils.rs +++ b/beacon_node/http_api/src/test_utils.rs @@ -293,6 +293,7 @@ pub async fn create_api_server_with_config( network_globals: Some(network_globals), beacon_processor_send: Some(beacon_processor_send), sse_logging_components: None, + version: "test".to_string(), }); let (listening_socket, server) = diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index ed7abead18a..1c7f4a4ac09 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -2792,7 +2792,7 @@ impl ApiTester { let result = self.client.get_node_version().await.unwrap().data; let expected = VersionData { - version: lighthouse_version::version_with_platform(), + version: "test".to_string(), }; assert_eq!(result, expected); diff --git a/beacon_node/http_metrics/Cargo.toml b/beacon_node/http_metrics/Cargo.toml index b74c04a4cb6..5b45260cbce 100644 --- a/beacon_node/http_metrics/Cargo.toml +++ b/beacon_node/http_metrics/Cargo.toml @@ -9,7 +9,6 @@ edition = { workspace = true } beacon_chain = { workspace = true } health_metrics = { workspace = true } lighthouse_network = { workspace = true } -lighthouse_version = { workspace = true } logging = { workspace = true } malloc_utils = { workspace = true } metrics = { workspace = true } diff --git a/beacon_node/http_metrics/src/lib.rs b/beacon_node/http_metrics/src/lib.rs index cfa55b54eba..6a88081c42a 100644 --- a/beacon_node/http_metrics/src/lib.rs +++ b/beacon_node/http_metrics/src/lib.rs @@ -5,7 +5,6 @@ mod metrics; use beacon_chain::{BeaconChain, BeaconChainTypes}; use lighthouse_network::prometheus_client::registry::Registry; -use lighthouse_version::version_with_platform; use logging::crit; use serde::{Deserialize, Serialize}; use std::future::Future; @@ -42,6 +41,7 @@ pub struct Context { pub db_path: Option, pub freezer_db_path: Option, pub gossipsub_registry: Option>, + pub version: String, } /// Configuration for the HTTP server. @@ -86,6 +86,7 @@ pub fn serve( shutdown: impl Future + Send + Sync + 'static, ) -> Result<(SocketAddr, impl Future), Error> { let config = &ctx.config; + let version = ctx.version.clone(); // Configure CORS. let cors_builder = { @@ -132,7 +133,7 @@ pub fn serve( ) }) // Add a `Server` header. - .map(|reply| warp::reply::with_header(reply, "Server", &version_with_platform())) + .map(move |reply| warp::reply::with_header(reply, "Server", &version)) .with(cors_builder.build()); let (listening_socket, server) = warp::serve(routes).try_bind_with_graceful_shutdown( diff --git a/beacon_node/http_metrics/tests/tests.rs b/beacon_node/http_metrics/tests/tests.rs index 2ce21a62b39..f060c051756 100644 --- a/beacon_node/http_metrics/tests/tests.rs +++ b/beacon_node/http_metrics/tests/tests.rs @@ -26,6 +26,7 @@ async fn returns_200_ok() { db_path: None, freezer_db_path: None, gossipsub_registry: None, + version: "test".to_string(), }); let ctx = context.clone(); diff --git a/beacon_node/lighthouse_network/Cargo.toml b/beacon_node/lighthouse_network/Cargo.toml index efb6f27dc52..eeb44438cda 100644 --- a/beacon_node/lighthouse_network/Cargo.toml +++ b/beacon_node/lighthouse_network/Cargo.toml @@ -28,7 +28,6 @@ gossipsub = { workspace = true } hex = { workspace = true } itertools = { workspace = true } libp2p-mplex = "0.43" -lighthouse_version = { workspace = true } local-ip-address = "0.6" logging = { workspace = true } lru = { workspace = true } diff --git a/beacon_node/lighthouse_network/src/config.rs b/beacon_node/lighthouse_network/src/config.rs index 416ca73e08e..444df049ec3 100644 --- a/beacon_node/lighthouse_network/src/config.rs +++ b/beacon_node/lighthouse_network/src/config.rs @@ -82,9 +82,15 @@ pub struct Config { /// Disables peer scoring altogether. pub disable_peer_scoring: bool, - /// Client version + /// Client version (e.g. "Lighthouse/v8.0.0-67da032/x86_64-linux") pub client_version: String, + /// Client name for ENR (e.g. "Lighthouse") + pub enr_client_name: String, + + /// Semantic version for ENR (e.g. "8.0.0") + pub enr_version: String, + /// Disables the discovery protocol from starting. pub disable_discovery: bool, @@ -346,7 +352,9 @@ impl Default for Config { libp2p_nodes: vec![], trusted_peers: vec![], disable_peer_scoring: false, - client_version: lighthouse_version::version_with_platform(), + client_version: String::new(), + enr_client_name: String::new(), + enr_version: String::new(), disable_discovery: false, disable_quic_support: false, upnp_enabled: true, diff --git a/beacon_node/lighthouse_network/src/discovery/enr.rs b/beacon_node/lighthouse_network/src/discovery/enr.rs index 4c285ea86c8..bd6ef064c32 100644 --- a/beacon_node/lighthouse_network/src/discovery/enr.rs +++ b/beacon_node/lighthouse_network/src/discovery/enr.rs @@ -7,7 +7,6 @@ use crate::NetworkConfig; use crate::types::{Enr, EnrAttestationBitfield, EnrSyncCommitteeBitfield}; use alloy_rlp::bytes::Bytes; use libp2p::identity::Keypair; -use lighthouse_version::{client_name, version}; use network_utils::enr_ext::CombinedKeyExt; use network_utils::enr_ext::{EnrExt, QUIC_ENR_KEY, QUIC6_ENR_KEY}; use ssz::{Decode, Encode}; @@ -210,7 +209,11 @@ pub fn build_enr( // Add EIP 7636 client information if !config.private { - builder.client_info(client_name().to_string(), version().to_string(), None); + builder.client_info( + config.enr_client_name.clone(), + config.enr_version.clone(), + None, + ); } // Add QUIC fields to the ENR. diff --git a/beacon_node/lighthouse_network/src/service/mod.rs b/beacon_node/lighthouse_network/src/service/mod.rs index 4eebda1decb..e9b59c67a7a 100644 --- a/beacon_node/lighthouse_network/src/service/mod.rs +++ b/beacon_node/lighthouse_network/src/service/mod.rs @@ -399,7 +399,7 @@ impl Network { .with_cache_size(0) } else { identify::Config::new("eth2/1.0.0".into(), local_public_key) - .with_agent_version(lighthouse_version::version_with_platform()) + .with_agent_version(config.client_version.clone()) .with_cache_size(0) }; identify::Behaviour::new(identify_config) diff --git a/common/monitoring_api/Cargo.toml b/common/monitoring_api/Cargo.toml index e00b1f027b6..eece1365f77 100644 --- a/common/monitoring_api/Cargo.toml +++ b/common/monitoring_api/Cargo.toml @@ -8,9 +8,7 @@ edition = { workspace = true } [dependencies] eth2 = { workspace = true, features = ["lighthouse"] } health_metrics = { workspace = true } -lighthouse_version = { workspace = true } metrics = { workspace = true } -regex = { workspace = true } reqwest = { workspace = true } sensitive_url = { workspace = true } serde = { workspace = true } diff --git a/common/monitoring_api/src/types.rs b/common/monitoring_api/src/types.rs index cf33ccb9c04..e73040b96e6 100644 --- a/common/monitoring_api/src/types.rs +++ b/common/monitoring_api/src/types.rs @@ -76,7 +76,7 @@ impl From for ProcessMetrics { cpu_process_seconds_total: health.pid_process_seconds_total, memory_process_bytes: health.pid_mem_resident_set_size, client_name: CLIENT_NAME.to_string(), - client_version: client_version().unwrap_or_default(), + client_version: client_version(), client_build: client_build(), } } @@ -164,10 +164,8 @@ pub struct ValidatorProcessMetrics { } /// Returns the client version -fn client_version() -> Option { - let re = regex::Regex::new(r"\d+\.\d+\.\d+").expect("Regex is valid"); - re.find(lighthouse_version::VERSION) - .map(|m| m.as_str().to_string()) +fn client_version() -> String { + env!("CARGO_PKG_VERSION").to_string() } /// Returns the client build diff --git a/lighthouse/src/main.rs b/lighthouse/src/main.rs index c93016a0f54..fe53d97a742 100644 --- a/lighthouse/src/main.rs +++ b/lighthouse/src/main.rs @@ -16,7 +16,7 @@ use environment::{EnvironmentBuilder, LoggerConfig}; use eth2_network_config::{DEFAULT_HARDCODED_NETWORK, Eth2NetworkConfig, HARDCODED_NET_NAMES}; use ethereum_hashing::have_sha_extensions; use futures::TryFutureExt; -use lighthouse_version::VERSION; +use lighthouse_version::{COMMIT_PREFIX, VERSION, client_name, version, version_with_platform}; use logging::{MetricsLayer, build_workspace_filter, crit}; use malloc_utils::configure_memory_allocator; use opentelemetry::trace::TracerProvider; @@ -783,8 +783,9 @@ fn run( Ok(LighthouseSubcommands::ValidatorClient(validator_client_config)) => { let context = environment.core_context(); let executor = context.executor.clone(); - let config = validator_client::Config::from_cli(matches, &validator_client_config) + let mut config = validator_client::Config::from_cli(matches, &validator_client_config) .map_err(|e| format!("Unable to initialize validator config: {}", e))?; + config.version_with_platform = version_with_platform(); // Dump configs if `dump-config` or `dump-chain-config` flags are set clap_utils::check_dump_configs::<_, E>(matches, &config, &context.eth2_config.spec)?; @@ -823,6 +824,18 @@ fn run( let executor = context.executor.clone(); let mut config = beacon_node::get_config::(matches, &context)?; config.logger_config = logger_config; + + // Set version fields from the binary's lighthouse_version crate. + config.version = VERSION.to_string(); + config.version_with_platform = version_with_platform(); + config.commit_prefix = COMMIT_PREFIX.to_string(); + config.network.client_version = version_with_platform(); + config.network.enr_client_name = client_name().to_string(); + config.network.enr_version = version().to_string(); + if let Some(ref mut el_config) = config.execution_layer { + el_config.version = VERSION.to_string(); + el_config.commit_prefix = COMMIT_PREFIX.to_string(); + } // Dump configs if `dump-config` or `dump-chain-config` flags are set clap_utils::check_dump_configs::<_, E>(matches, &config, &context.eth2_config.spec)?; diff --git a/validator_client/http_api/Cargo.toml b/validator_client/http_api/Cargo.toml index 2bd57867acf..0c807a8e376 100644 --- a/validator_client/http_api/Cargo.toml +++ b/validator_client/http_api/Cargo.toml @@ -25,7 +25,6 @@ graffiti_file = { workspace = true } health_metrics = { workspace = true } initialized_validators = { workspace = true } lighthouse_validator_store = { workspace = true } -lighthouse_version = { workspace = true } logging = { workspace = true } parking_lot = { workspace = true } rand = { workspace = true } diff --git a/validator_client/http_api/src/lib.rs b/validator_client/http_api/src/lib.rs index a35b4ec6c6d..9b018915da4 100644 --- a/validator_client/http_api/src/lib.rs +++ b/validator_client/http_api/src/lib.rs @@ -36,7 +36,6 @@ use eth2::lighthouse_vc::{ }, }; use health_metrics::observe::Observe; -use lighthouse_version::version_with_platform; use logging::SSELoggingComponents; use logging::crit; use parking_lot::RwLock; @@ -94,6 +93,7 @@ pub struct Context { pub config: Config, pub sse_logging_components: Option, pub slot_clock: T, + pub version: String, } /// Configuration for the HTTP server. @@ -151,6 +151,7 @@ pub fn serve( shutdown: impl Future + Send + Sync + 'static, ) -> Result<(SocketAddr, impl Future), Error> { let config = &ctx.config; + let version = ctx.version.clone(); let allow_keystore_export = config.allow_keystore_export; let store_passwords_in_secrets_dir = config.store_passwords_in_secrets_dir; let use_long_timeouts = config.bn_long_timeouts; @@ -289,12 +290,16 @@ pub fn serve( let get_node_version = warp::path("lighthouse") .and(warp::path("version")) .and(warp::path::end()) - .then(|| { - blocking_json_task(move || { - Ok(api_types::GenericResponse::from(api_types::VersionData { - version: version_with_platform(), - })) - }) + .then({ + let version = version.clone(); + move || { + let version = version.clone(); + blocking_json_task(move || { + Ok(api_types::GenericResponse::from(api_types::VersionData { + version, + })) + }) + } }); // GET lighthouse/health @@ -1396,7 +1401,7 @@ pub fn serve( // Maps errors into HTTP responses. .recover(warp_utils::reject::handle_rejection) // Add a `Server` header. - .map(|reply| warp::reply::with_header(reply, "Server", &version_with_platform())) + .map(move |reply| warp::reply::with_header(reply, "Server", &version)) .with(cors_builder.build()); let (listening_socket, server) = warp::serve(routes).try_bind_with_graceful_shutdown( diff --git a/validator_client/http_api/src/test_utils.rs b/validator_client/http_api/src/test_utils.rs index f83d9f4d526..c2e6000f6ea 100644 --- a/validator_client/http_api/src/test_utils.rs +++ b/validator_client/http_api/src/test_utils.rs @@ -142,6 +142,7 @@ impl ApiTester { config: http_config, sse_logging_components: None, slot_clock, + version: "test".to_string(), }); let ctx = context; let (shutdown_tx, shutdown_rx) = oneshot::channel(); @@ -272,7 +273,7 @@ impl ApiTester { let result = self.client.get_lighthouse_version().await.unwrap().data; let expected = VersionData { - version: lighthouse_version::version_with_platform(), + version: "test".to_string(), }; assert_eq!(result, expected); diff --git a/validator_client/http_api/src/tests.rs b/validator_client/http_api/src/tests.rs index 5cb631983cc..131768655fe 100644 --- a/validator_client/http_api/src/tests.rs +++ b/validator_client/http_api/src/tests.rs @@ -132,6 +132,7 @@ impl ApiTester { }, sse_logging_components: None, slot_clock: slot_clock.clone(), + version: "test".to_string(), }); let ctx = context.clone(); let (listening_socket, server) = @@ -237,7 +238,7 @@ impl ApiTester { let result = self.client.get_lighthouse_version().await.unwrap().data; let expected = VersionData { - version: lighthouse_version::version_with_platform(), + version: "test".to_string(), }; assert_eq!(result, expected); diff --git a/validator_client/http_metrics/Cargo.toml b/validator_client/http_metrics/Cargo.toml index 24cbff7cde6..3ab1ee43d30 100644 --- a/validator_client/http_metrics/Cargo.toml +++ b/validator_client/http_metrics/Cargo.toml @@ -7,7 +7,6 @@ authors = ["Sigma Prime "] [dependencies] health_metrics = { workspace = true } lighthouse_validator_store = { workspace = true } -lighthouse_version = { workspace = true } logging = { workspace = true } malloc_utils = { workspace = true } metrics = { workspace = true } diff --git a/validator_client/http_metrics/src/lib.rs b/validator_client/http_metrics/src/lib.rs index 70b447a4939..09038d8ea4f 100644 --- a/validator_client/http_metrics/src/lib.rs +++ b/validator_client/http_metrics/src/lib.rs @@ -3,7 +3,6 @@ //! For other endpoints, see the `http_api` crate. use lighthouse_validator_store::LighthouseValidatorStore; -use lighthouse_version::version_with_platform; use logging::crit; use malloc_utils::scrape_allocator_metrics; use parking_lot::RwLock; @@ -51,6 +50,7 @@ pub struct Shared { pub struct Context { pub config: Config, pub shared: RwLock>, + pub version: String, } /// Configuration for the HTTP server. @@ -95,6 +95,7 @@ pub fn serve( shutdown: impl Future + Send + Sync + 'static, ) -> Result<(SocketAddr, impl Future), Error> { let config = &ctx.config; + let version = ctx.version.clone(); // Configure CORS. let cors_builder = { @@ -141,7 +142,7 @@ pub fn serve( ) }) // Add a `Server` header. - .map(|reply| warp::reply::with_header(reply, "Server", &version_with_platform())) + .map(move |reply| warp::reply::with_header(reply, "Server", &version)) .with(cors_builder.build()); let (listening_socket, server) = warp::serve(routes).try_bind_with_graceful_shutdown( diff --git a/validator_client/src/config.rs b/validator_client/src/config.rs index 1a286a74dc1..a025c92a16c 100644 --- a/validator_client/src/config.rs +++ b/validator_client/src/config.rs @@ -90,6 +90,9 @@ pub struct Config { #[serde(flatten)] pub initialized_validators: InitializedValidatorsConfig, pub disable_attesting: bool, + /// Version with platform info for HTTP Server headers. Set by the binary. + #[serde(skip)] + pub version_with_platform: String, } impl Default for Config { @@ -136,6 +139,7 @@ impl Default for Config { distributed: false, initialized_validators: <_>::default(), disable_attesting: false, + version_with_platform: String::new(), } } } diff --git a/validator_client/src/lib.rs b/validator_client/src/lib.rs index 23541cf6e28..0ed2d5be360 100644 --- a/validator_client/src/lib.rs +++ b/validator_client/src/lib.rs @@ -141,6 +141,7 @@ impl ProductionValidatorClient { Arc::new(validator_http_metrics::Context { config: config.http_metrics.clone(), shared: RwLock::new(shared), + version: config.version_with_platform.clone(), }); let exit = context.executor.exit(); @@ -562,6 +563,7 @@ impl ProductionValidatorClient { config: self.config.http_api.clone(), sse_logging_components: self.context.sse_logging_components.clone(), slot_clock: self.slot_clock.clone(), + version: self.config.version_with_platform.clone(), }); let exit = self.context.executor.exit();