Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
3 changes: 2 additions & 1 deletion crates/anvil/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![cfg_attr(docsrs, feature(doc_cfg))]

use crate::{
error::{NodeError, NodeResult},
eth::{
EthApi,
backend::{info::StorageInfo, mem},
Expand All @@ -14,7 +15,6 @@ use crate::{
},
filter::Filters,
logging::{LoggingManager, NodeLogLayer},
server::error::{NodeError, NodeResult},
service::NodeService,
shutdown::Signal,
tasks::TaskManager,
Expand Down Expand Up @@ -51,6 +51,7 @@ pub use config::{

mod hardfork;
pub use alloy_hardforks::EthereumHardfork;
mod error;
/// ethereum related implementations
pub mod eth;
/// Evm related abstractions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::beacon_error::BeaconError;
use super::{error::BeaconError, utils::must_be_ssz};
use crate::eth::EthApi;
use alloy_eips::BlockId;
use alloy_primitives::{B256, aliases::B32};
Expand All @@ -15,44 +15,6 @@ use axum::{
use ssz::Encode;
use std::{collections::HashMap, str::FromStr as _};

/// Helper function to determine if the Accept header indicates a preference for SSZ (octet-stream)
/// over JSON.
pub fn must_be_ssz(headers: &HeaderMap) -> bool {
headers
.get(axum::http::header::ACCEPT)
.and_then(|v| v.to_str().ok())
.map(|accept_str| {
let mut octet_stream_q = 0.0;
let mut json_q = 0.0;

// Parse each media type in the Accept header
for media_type in accept_str.split(',') {
let media_type = media_type.trim();
let quality = media_type
.split(';')
.find_map(|param| {
let param = param.trim();
if let Some(q) = param.strip_prefix("q=") {
q.parse::<f32>().ok()
} else {
None
}
})
.unwrap_or(1.0); // Default quality factor is 1.0

if media_type.starts_with("application/octet-stream") {
octet_stream_q = quality;
} else if media_type.starts_with("application/json") {
json_q = quality;
}
}

// Prefer octet-stream if it has higher quality factor
octet_stream_q > json_q
})
.unwrap_or(false)
}

/// Handles incoming Beacon API requests for blob sidecars
///
/// This endpoint is deprecated. Use `GET /eth/v1/beacon/blobs/{block_id}` instead.
Expand Down
18 changes: 18 additions & 0 deletions crates/anvil/src/server/beacon/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! Beacon Node REST API implementation for Anvil.

use axum::{Router, routing::get};

use crate::eth::EthApi;

mod error;
mod handlers;
mod utils;

/// Configures an [`axum::Router`] that handles Beacon REST API calls.
pub fn router(api: EthApi) -> Router {
Router::new()
.route("/eth/v1/beacon/blob_sidecars/{block_id}", get(handlers::handle_get_blob_sidecars))
.route("/eth/v1/beacon/blobs/{block_id}", get(handlers::handle_get_blobs))
.route("/eth/v1/beacon/genesis", get(handlers::handle_get_genesis))
.with_state(api)
}
39 changes: 39 additions & 0 deletions crates/anvil/src/server/beacon/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use hyper::HeaderMap;

/// Helper function to determine if the Accept header indicates a preference for SSZ (octet-stream)
/// over JSON.
pub fn must_be_ssz(headers: &HeaderMap) -> bool {
headers
.get(axum::http::header::ACCEPT)
.and_then(|v| v.to_str().ok())
.map(|accept_str| {
let mut octet_stream_q = 0.0;
let mut json_q = 0.0;

// Parse each media type in the Accept header
for media_type in accept_str.split(',') {
let media_type = media_type.trim();
let quality = media_type
.split(';')
.find_map(|param| {
let param = param.trim();
if let Some(q) = param.strip_prefix("q=") {
q.parse::<f32>().ok()
} else {
None
}
})
.unwrap_or(1.0); // Default quality factor is 1.0

if media_type.starts_with("application/octet-stream") {
octet_stream_q = quality;
} else if media_type.starts_with("application/json") {
json_q = quality;
}
}

// Prefer octet-stream if it has higher quality factor
octet_stream_q > json_q
})
.unwrap_or(false)
}
27 changes: 7 additions & 20 deletions crates/anvil/src/server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
//! Contains the code to launch an Ethereum RPC server.
//! This module provides the infrastructure to launch an Ethereum JSON-RPC server
//! (via HTTP, WebSocket, and IPC) and Beacon Node REST API.

use crate::{EthApi, IpcTask};
use anvil_server::{ServerConfig, ipc::IpcEndpoint};
use axum::{Router, routing::get};
use axum::Router;
use futures::StreamExt;
use handler::{HttpEthRpcHandler, PubSubEthRpcHandler};
use rpc_handlers::{HttpEthRpcHandler, PubSubEthRpcHandler};
use std::{io, net::SocketAddr, pin::pin};
use tokio::net::TcpListener;

mod beacon_error;
mod beacon_handler;
pub mod error;
mod handler;
mod beacon;
mod rpc_handlers;

/// Configures a server that handles [`EthApi`] related JSON-RPC calls via HTTP and WS.
///
Expand Down Expand Up @@ -45,24 +44,12 @@ pub fn router(api: EthApi, config: ServerConfig) -> Router {
let rpc_router = anvil_server::http_ws_router(config, http, ws);

// Beacon REST API router
let beacon_router = beacon_router(api);
let beacon_router = beacon::router(api);

// Merge the routers
rpc_router.merge(beacon_router)
}

/// Configures an [`axum::Router`] that handles Beacon REST API calls.
fn beacon_router(api: EthApi) -> Router {
Router::new()
.route(
"/eth/v1/beacon/blob_sidecars/{block_id}",
get(beacon_handler::handle_get_blob_sidecars),
)
.route("/eth/v1/beacon/blobs/{block_id}", get(beacon_handler::handle_get_blobs))
.route("/eth/v1/beacon/genesis", get(beacon_handler::handle_get_genesis))
.with_state(api)
}

/// Launches an ipc server at the given path in a new task
///
/// # Panics
Expand Down
Loading