Files
lighthouse/beacon_node/http_api/src/beacon/execution_payload_bids.rs
Mac L 8c2a909061 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>
2026-06-25 14:19:29 +00:00

116 lines
3.9 KiB
Rust

use crate::task_spawner::{Priority, TaskSpawner};
use crate::utils::{
ChainFilter, EthV1Filter, NetworkTxFilter, ResponseFilter, TaskSpawnerFilter,
publish_pubsub_message,
};
use beacon_chain::{BeaconChain, BeaconChainTypes};
use bytes::Bytes;
use lighthouse_network::PubsubMessage;
use network::NetworkMessage;
use ssz::Decode;
use std::sync::Arc;
use tokio::sync::mpsc::UnboundedSender;
use tracing::{debug, warn};
use types::SignedExecutionPayloadBid;
use warp::{
Filter, Rejection,
reply::{Reply, Response},
};
// POST /eth/v1/beacon/execution_payload_bids (SSZ)
pub(crate) fn post_beacon_execution_payload_bids_ssz<T: BeaconChainTypes>(
eth_v1: EthV1Filter,
task_spawner_filter: TaskSpawnerFilter<T>,
chain_filter: ChainFilter<T>,
network_tx_filter: NetworkTxFilter<T>,
) -> ResponseFilter {
eth_v1
.and(warp::path("beacon"))
.and(warp::path("execution_payload_bids"))
.and(warp::path::end())
.and(warp::body::bytes())
.and(task_spawner_filter)
.and(chain_filter)
.and(network_tx_filter)
.then(
|body_bytes: Bytes,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>| {
task_spawner.blocking_response_task(Priority::P0, move || {
let bid = SignedExecutionPayloadBid::<T::EthSpec>::from_ssz_bytes(&body_bytes)
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!("invalid SSZ: {e:?}"))
})?;
publish_execution_payload_bid(bid, &chain, &network_tx)
})
},
)
.boxed()
}
// POST /eth/v1/beacon/execution_payload_bids
pub(crate) fn post_beacon_execution_payload_bids<T: BeaconChainTypes>(
eth_v1: EthV1Filter,
task_spawner_filter: TaskSpawnerFilter<T>,
chain_filter: ChainFilter<T>,
network_tx_filter: NetworkTxFilter<T>,
) -> ResponseFilter {
eth_v1
.and(warp::path("beacon"))
.and(warp::path("execution_payload_bids"))
.and(warp::path::end())
.and(warp::body::json())
.and(task_spawner_filter)
.and(chain_filter)
.and(network_tx_filter)
.then(
|bid: SignedExecutionPayloadBid<T::EthSpec>,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>| {
task_spawner.blocking_response_task(Priority::P0, move || {
publish_execution_payload_bid(bid, &chain, &network_tx)
})
},
)
.boxed()
}
pub fn publish_execution_payload_bid<T: BeaconChainTypes>(
bid: SignedExecutionPayloadBid<T::EthSpec>,
chain: &Arc<BeaconChain<T>>,
network_tx: &UnboundedSender<NetworkMessage<T::EthSpec>>,
) -> Result<Response, Rejection> {
let slot = bid.slot();
let builder_index = bid.message.builder_index;
if !chain.spec.is_gloas_scheduled() {
return Err(warp_utils::reject::custom_bad_request(
"Execution payload bids are not supported before the Gloas fork".into(),
));
}
debug!(
%slot,
builder_index,
"Publishing signed execution payload bid to network"
);
let gossip_verified_bid = chain
.verify_payload_bid_for_gossip(Arc::new(bid))
.map_err(|e| {
warn!(%slot, error = ?e, "Execution payload bid failed gossip verification");
warp_utils::reject::custom_bad_request(format!("bid failed gossip verification: {e}"))
})?;
let bid_for_gossip = gossip_verified_bid.signed_bid.as_ref().clone();
publish_pubsub_message(
network_tx,
PubsubMessage::ExecutionPayloadBid(Box::new(bid_for_gossip)),
)?;
Ok(warp::reply().into_response())
}