Reduce eth2 dependency space (#8524)

Remove certain dependencies from `eth2`, and feature-gate others which are only used by certain endpoints.

| Removed | Optional | Dev only |
| -------- | -------- | -------- |
| `either` `enr` `libp2p-identity` `multiaddr` | `protoarray` `eth2_keystore` `eip_3076` `zeroize` `reqwest-eventsource` `futures` `futures-util` | `rand` `test_random_derive` |

This is done by adding an `events` feature which enables the events endpoint and its associated dependencies.
The `lighthouse` feature also enables its associated dependencies making them optional.

The networking-adjacent dependencies were removed by just having certain fields use a `String` instead of an explicit network type. This means the user should handle conversion at the call site instead. This is a bit spicy, but I believe `PeerId`, `Enr` and `Multiaddr` are easily converted to and from `String`s so I think it's fine and reduces our dependency space by a lot. The alternative is to feature gate these types behind a `network` feature instead.


Co-Authored-By: Mac L <mjladson@pm.me>
This commit is contained in:
Mac L
2025-12-08 09:37:23 +04:00
committed by GitHub
parent 2afa87879b
commit 7bfcc03520
14 changed files with 61 additions and 46 deletions

4
Cargo.lock generated
View File

@@ -3128,17 +3128,13 @@ dependencies = [
"context_deserialize",
"educe",
"eip_3076",
"either",
"enr",
"eth2_keystore",
"ethereum_serde_utils",
"ethereum_ssz",
"ethereum_ssz_derive",
"futures",
"futures-util",
"libp2p-identity",
"mediatype",
"multiaddr",
"pretty_reqwest_error",
"proto_array",
"rand 0.9.2",

View File

@@ -19,7 +19,7 @@ alloy-primitives = { workspace = true }
bitvec = { workspace = true }
bls = { workspace = true }
educe = { workspace = true }
eth2 = { workspace = true }
eth2 = { workspace = true, features = ["lighthouse"] }
eth2_network_config = { workspace = true }
ethereum_hashing = { workspace = true }
ethereum_serde_utils = { workspace = true }

View File

@@ -12,7 +12,7 @@ alloy-rpc-types-eth = { workspace = true }
arc-swap = "1.6.0"
builder_client = { path = "../builder_client" }
bytes = { workspace = true }
eth2 = { workspace = true }
eth2 = { workspace = true, features = ["events", "lighthouse"] }
ethereum_serde_utils = { workspace = true }
ethereum_ssz = { workspace = true }
fixed_bytes = { workspace = true }

View File

@@ -12,7 +12,7 @@ bs58 = "0.4.0"
bytes = { workspace = true }
directory = { workspace = true }
either = { workspace = true }
eth2 = { workspace = true }
eth2 = { workspace = true, features = ["lighthouse"] }
ethereum_serde_utils = { workspace = true }
ethereum_ssz = { workspace = true }
execution_layer = { workspace = true }

View File

@@ -2118,9 +2118,12 @@ pub fn serve<T: BeaconChainTypes>(
let discovery_addresses = enr.multiaddr_p2p_udp();
Ok(api_types::GenericResponse::from(api_types::IdentityData {
peer_id: network_globals.local_peer_id().to_base58(),
enr,
p2p_addresses,
discovery_addresses,
enr: enr.to_base64(),
p2p_addresses: p2p_addresses.iter().map(|a| a.to_string()).collect(),
discovery_addresses: discovery_addresses
.iter()
.map(|a| a.to_string())
.collect(),
metadata: utils::from_meta_data::<T::EthSpec>(
&network_globals.local_metadata,
&chain.spec,

View File

@@ -2853,9 +2853,19 @@ impl ApiTester {
let expected = IdentityData {
peer_id: self.local_enr.peer_id().to_string(),
enr: self.local_enr.clone(),
p2p_addresses: self.local_enr.multiaddr_p2p_tcp(),
discovery_addresses: self.local_enr.multiaddr_p2p_udp(),
enr: self.local_enr.to_base64(),
p2p_addresses: self
.local_enr
.multiaddr_p2p_tcp()
.iter()
.map(|a| a.to_string())
.collect(),
discovery_addresses: self
.local_enr
.multiaddr_p2p_udp()
.iter()
.map(|a| a.to_string())
.collect(),
metadata: MetaData::V2(MetaDataV2 {
seq_number: 0,
attnets: "0x0000000000000000".to_string(),
@@ -2884,7 +2894,7 @@ impl ApiTester {
pub async fn test_get_node_peers_by_id(self) -> Self {
let result = self
.client
.get_node_peers_by_id(self.external_peer_id)
.get_node_peers_by_id(&self.external_peer_id.to_string())
.await
.unwrap()
.data;

View File

@@ -17,7 +17,7 @@ directory = { workspace = true }
dirs = { workspace = true }
discv5 = { workspace = true }
either = { workspace = true }
eth2 = { workspace = true }
eth2 = { workspace = true, features = ["lighthouse"] }
ethereum_ssz = { workspace = true }
ethereum_ssz_derive = { workspace = true }
fnv = { workspace = true }

View File

@@ -5,36 +5,33 @@ authors = ["Paul Hauner <paul@paulhauner.com>"]
edition = { workspace = true }
[features]
default = ["lighthouse"]
lighthouse = []
default = []
lighthouse = ["proto_array", "eth2_keystore", "eip_3076", "zeroize"]
events = ["reqwest-eventsource", "futures", "futures-util"]
[dependencies]
context_deserialize = { workspace = true }
educe = { workspace = true }
eip_3076 = { workspace = true }
either = { workspace = true }
enr = { version = "0.13.0", features = ["ed25519"] }
eth2_keystore = { workspace = true }
eip_3076 = { workspace = true, optional = true }
eth2_keystore = { workspace = true, optional = true }
ethereum_serde_utils = { workspace = true }
ethereum_ssz = { workspace = true }
ethereum_ssz_derive = { workspace = true }
futures = { workspace = true }
futures-util = "0.3.8"
libp2p-identity = { version = "0.2", features = ["peerid"] }
futures = { workspace = true, optional = true }
futures-util = { version = "0.3.8", optional = true }
mediatype = "0.19.13"
multiaddr = "0.18.2"
pretty_reqwest_error = { workspace = true }
proto_array = { workspace = true }
rand = { workspace = true }
proto_array = { workspace = true, optional = true }
reqwest = { workspace = true }
reqwest-eventsource = "0.6.0"
reqwest-eventsource = { version = "0.6.0", optional = true }
sensitive_url = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
ssz_types = { workspace = true }
test_random_derive = { path = "../../common/test_random_derive" }
types = { workspace = true }
zeroize = { workspace = true }
zeroize = { workspace = true, optional = true }
[dev-dependencies]
rand = { workspace = true }
test_random_derive = { path = "../../common/test_random_derive" }
tokio = { workspace = true }

View File

@@ -14,6 +14,7 @@ use std::{fmt, path::PathBuf};
pub enum Error {
/// The `reqwest` client raised an error.
HttpClient(PrettyReqwestError),
#[cfg(feature = "events")]
/// The `reqwest_eventsource` client raised an error.
SseClient(Box<reqwest_eventsource::Error>),
/// The server returned an error message where the body was able to be parsed.
@@ -91,6 +92,7 @@ impl Error {
pub fn status(&self) -> Option<StatusCode> {
match self {
Error::HttpClient(error) => error.inner().status(),
#[cfg(feature = "events")]
Error::SseClient(error) => {
if let reqwest_eventsource::Error::InvalidStatusCode(status, _) = error.as_ref() {
Some(*status)

View File

@@ -22,20 +22,23 @@ pub use beacon_response::{
};
pub use self::error::{Error, ok_or_error, success_or_error};
pub use reqwest;
pub use reqwest::{StatusCode, Url};
pub use sensitive_url::SensitiveUrl;
use self::mixin::{RequestAccept, ResponseOptional};
use self::types::*;
use educe::Educe;
#[cfg(feature = "events")]
use futures::Stream;
#[cfg(feature = "events")]
use futures_util::StreamExt;
use libp2p_identity::PeerId;
pub use reqwest;
use reqwest::{
Body, IntoUrl, RequestBuilder, Response,
header::{HeaderMap, HeaderValue},
};
pub use reqwest::{StatusCode, Url};
#[cfg(feature = "events")]
use reqwest_eventsource::{Event, EventSource};
pub use sensitive_url::SensitiveUrl;
use serde::{Serialize, de::DeserializeOwned};
use ssz::Encode;
use std::fmt;
@@ -1978,7 +1981,7 @@ impl BeaconNodeHttpClient {
/// `GET node/peers/{peer_id}`
pub async fn get_node_peers_by_id(
&self,
peer_id: PeerId,
peer_id: &str,
) -> Result<GenericResponse<PeerData>, Error> {
let mut path = self.eth_path(V1)?;
@@ -1986,7 +1989,7 @@ impl BeaconNodeHttpClient {
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("node")
.push("peers")
.push(&peer_id.to_string());
.push(peer_id);
self.get(path).await
}
@@ -2761,6 +2764,7 @@ impl BeaconNodeHttpClient {
}
/// `GET events?topics`
#[cfg(feature = "events")]
pub async fn get_events<E: EthSpec>(
&self,
topic: &[EventTopic],

View File

@@ -1,13 +1,13 @@
//! This module exposes a superset of the `types` crate. It adds additional types that are only
//! required for the HTTP API.
pub use types::*;
use crate::{
CONSENSUS_BLOCK_VALUE_HEADER, CONSENSUS_VERSION_HEADER, EXECUTION_PAYLOAD_BLINDED_HEADER,
EXECUTION_PAYLOAD_VALUE_HEADER, Error as ServerError,
};
use enr::{CombinedKey, Enr};
use mediatype::{MediaType, MediaTypeList, names};
use multiaddr::Multiaddr;
use reqwest::header::HeaderMap;
use serde::{Deserialize, Deserializer, Serialize};
use serde_utils::quoted_u64::Quoted;
@@ -18,9 +18,11 @@ use std::fmt::{self, Display};
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
#[cfg(test)]
use test_random_derive::TestRandom;
#[cfg(test)]
use types::test_utils::TestRandom;
pub use types::*;
// TODO(mac): Temporary module and re-export hack to expose old `consensus/types` via `eth2/types`.
pub use crate::beacon_response::*;
@@ -557,9 +559,9 @@ pub struct ChainHeadData {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IdentityData {
pub peer_id: String,
pub enr: Enr<CombinedKey>,
pub p2p_addresses: Vec<Multiaddr>,
pub discovery_addresses: Vec<Multiaddr>,
pub enr: String,
pub p2p_addresses: Vec<String>,
pub discovery_addresses: Vec<String>,
pub metadata: MetaData,
}
@@ -2208,7 +2210,8 @@ pub enum ContentType {
Ssz,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom)]
#[cfg_attr(test, derive(TestRandom))]
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, Encode, Decode)]
#[serde(bound = "E: EthSpec")]
pub struct BlobsBundle<E: EthSpec> {
pub commitments: KzgCommitments<E>,

View File

@@ -4,7 +4,7 @@ version = "0.1.0"
edition = { workspace = true }
[dependencies]
eth2 = { workspace = true }
eth2 = { workspace = true, features = ["lighthouse"] }
metrics = { workspace = true }
[target.'cfg(target_os = "linux")'.dependencies]

View File

@@ -6,7 +6,7 @@ edition = { workspace = true }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
eth2 = { workspace = true }
eth2 = { workspace = true, features = ["lighthouse"] }
health_metrics = { workspace = true }
lighthouse_version = { workspace = true }
metrics = { workspace = true }

View File

@@ -16,7 +16,7 @@ deposit_contract = { workspace = true }
directory = { workspace = true }
dirs = { workspace = true }
doppelganger_service = { workspace = true }
eth2 = { workspace = true }
eth2 = { workspace = true, features = ["lighthouse"] }
eth2_keystore = { workspace = true }
ethereum_serde_utils = { workspace = true }
filesystem = { workspace = true }