Bump warp and begin axum migration (#9001)

- Bump `warp` to 0.4. This unifies `warp` and `axum` onto the same `http`, `hyper`, `h2`, `rustls`, etc versions.
- Create `axum_utils` which contain common functions and types
- Begins migration of all HTTP API servers from warp to axum


Co-Authored-By: Mac L <mjladson@pm.me>
This commit is contained in:
Mac L
2026-06-25 18:19:29 +04:00
committed by GitHub
parent a4c4cccf04
commit 8c2a909061
41 changed files with 1333 additions and 543 deletions

View File

@@ -13,6 +13,8 @@ testing = ["dep:deposit_contract", "dep:doppelganger_service", "dep:tempfile"]
[dependencies]
account_utils = { workspace = true }
axum = { workspace = true }
axum_utils = { workspace = true }
beacon_node_fallback = { workspace = true }
bls = { workspace = true }
deposit_contract = { workspace = true, optional = true }
@@ -42,6 +44,7 @@ sysinfo = { workspace = true }
system_health = { workspace = true }
task_executor = { workspace = true }
tempfile = { workspace = true, optional = true }
thiserror = { workspace = true }
tokio = { workspace = true }
tokio-stream = { workspace = true }
tracing = { workspace = true }

View File

@@ -9,23 +9,18 @@ mod keystores;
mod remotekeys;
mod tests;
pub use api_secret::PK_FILENAME;
use graffiti::{delete_graffiti, get_graffiti, set_graffiti};
use create_signed_voluntary_exit::create_signed_voluntary_exit;
use graffiti_file::{GraffitiFile, determine_graffiti};
use lighthouse_validator_store::LighthouseValidatorStore;
use validator_store::ValidatorStore;
pub use api_secret::{ApiSecret, PK_FILENAME};
use account_utils::{
mnemonic_from_phrase,
validator_definitions::{SigningDefinition, ValidatorDefinition, Web3SignerDefinition},
};
pub use api_secret::ApiSecret;
use axum::Router;
use axum_utils::server::Server;
use beacon_node_fallback::CandidateInfo;
use bls::{PublicKey, PublicKeyBytes};
use core::convert::Infallible;
use create_signed_voluntary_exit::create_signed_voluntary_exit;
use create_validator::{
create_validators_mnemonic, create_validators_web3signer, get_voting_password_storage,
};
@@ -37,7 +32,10 @@ use eth2::lighthouse_vc::{
UpdateCandidatesRequest, UpdateCandidatesResponse,
},
};
use graffiti::{delete_graffiti, get_graffiti, set_graffiti};
use graffiti_file::{GraffitiFile, determine_graffiti};
use health_metrics::observe::Observe;
use lighthouse_validator_store::LighthouseValidatorStore;
use lighthouse_version::version_with_platform;
use logging::SSELoggingComponents;
use logging::crit;
@@ -54,26 +52,27 @@ use sysinfo::{System, SystemExt};
use system_health::observe_system_health_vc;
use task_executor::TaskExecutor;
use tokio_stream::{StreamExt, wrappers::BroadcastStream};
use tracing::{info, warn};
use tracing::{error, info, warn};
use types::{ChainSpec, ConfigAndPreset, EthSpec};
use validator_dir::Builder as ValidatorDirBuilder;
use validator_services::block_service::BlockService;
use validator_store::ValidatorStore;
use warp::{Filter, reply::Response, sse::Event};
use warp_utils::reject::convert_rejection;
use warp_utils::task::blocking_json_task;
#[derive(Debug)]
#[derive(Debug, thiserror::Error)]
pub enum Error {
Warp(warp::Error),
#[error("Builder error: {0}")]
Builder(#[from] axum_utils::server::BuilderError),
#[error("Server error: {0}")]
Server(#[from] axum_utils::server::ServerError),
#[error("Warp error: {0}")]
Warp(#[from] warp::Error),
#[error("{0}")]
Other(String),
}
impl From<warp::Error> for Error {
fn from(e: warp::Error) -> Self {
Error::Warp(e)
}
}
impl From<String> for Error {
fn from(e: String) -> Self {
Error::Other(e)
@@ -148,7 +147,7 @@ impl Default for Config {
///
/// Returns an error if the server is unable to bind or there is another error during
/// configuration.
pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
pub async fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
ctx: Arc<Context<T, E>>,
shutdown: impl Future<Output = ()> + Send + Sync + 'static,
) -> Result<(SocketAddr, impl Future<Output = ()>), Error> {
@@ -1399,20 +1398,33 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
.recover(warp_utils::reject::handle_rejection)
// Add a `Server` header.
.map(|reply| warp::reply::with_header(reply, "Server", &version_with_platform()))
.with(cors_builder.build());
.with(cors_builder.build())
.boxed();
let (listening_socket, server) = warp::serve(routes).try_bind_with_graceful_shutdown(
SocketAddr::new(config.listen_addr, config.listen_port),
async {
shutdown.await;
},
)?;
let axum_router = Router::new().fallback_service(warp::service(routes));
let address = SocketAddr::new(config.listen_addr, config.listen_port);
let server = Server::builder(axum_router, address).build().await?;
let (address, server) = server.serve_with_shutdown(shutdown).await?;
info!(
listen_address = listening_socket.to_string(),
listen_address = %address,
?api_token_path,
"HTTP API started"
);
Ok((listening_socket, server))
let server_future = async move {
match server.await {
Ok(()) => {
info!("HTTP API server stopped");
}
Err(e) => {
error!(error = ?e, "HTTP API server error");
}
}
};
Ok((address, server_future))
}

View File

@@ -149,7 +149,7 @@ impl ApiTester {
// It's not really interesting why this triggered, just that it happened.
let _ = shutdown_rx.await;
};
let (listening_socket, server) = super::serve::<_, E>(ctx, server_shutdown).unwrap();
let (listening_socket, server) = super::serve::<_, E>(ctx, server_shutdown).await.unwrap();
tokio::spawn(server);

View File

@@ -135,7 +135,9 @@ impl ApiTester {
});
let ctx = context.clone();
let (listening_socket, server) =
super::serve::<_, E>(ctx, test_runtime.task_executor.exit()).unwrap();
super::serve::<_, E>(ctx, test_runtime.task_executor.exit())
.await
.unwrap();
tokio::spawn(server);