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
84 changes: 81 additions & 3 deletions beacon_node/http_api/src/beacon/execution_payload_envelope.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
use crate::block_id::BlockId;
use crate::task_spawner::{Priority, TaskSpawner};
use crate::utils::{ChainFilter, EthV1Filter, NetworkTxFilter, ResponseFilter, TaskSpawnerFilter};
use crate::version::{
ResponseIncludesVersion, add_consensus_version_header, add_ssz_content_type_header,
execution_optimistic_finalized_beacon_response,
};
use beacon_chain::{BeaconChain, BeaconChainTypes};
use bytes::Bytes;
use eth2::types as api_types;
use eth2::{CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER};
use lighthouse_network::PubsubMessage;
use network::NetworkMessage;
use ssz::Decode;
use ssz::{Decode, Encode};
use std::sync::Arc;
use tokio::sync::mpsc::UnboundedSender;
use tracing::{info, warn};
use types::SignedExecutionPayloadEnvelope;
use warp::{Filter, Rejection, Reply, reply::Response};
use warp::{
Filter, Rejection, Reply,
hyper::{Body, Response},
};

// POST beacon/execution_payload_envelope (SSZ)
pub(crate) fn post_beacon_execution_payload_envelope_ssz<T: BeaconChainTypes>(
Expand Down Expand Up @@ -81,7 +90,7 @@ pub async fn publish_execution_payload_envelope<T: BeaconChainTypes>(
envelope: SignedExecutionPayloadEnvelope<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
network_tx: &UnboundedSender<NetworkMessage<T::EthSpec>>,
) -> Result<Response, Rejection> {
) -> Result<Response<Body>, Rejection> {
let slot = envelope.message.slot;
let beacon_block_root = envelope.message.beacon_block_root;

Expand Down Expand Up @@ -114,3 +123,72 @@ pub async fn publish_execution_payload_envelope<T: BeaconChainTypes>(

Ok(warp::reply().into_response())
}

// TODO(gloas): add tests for this endpoint once we support importing payloads into the db
// GET beacon/execution_payload_envelope/{block_id}
pub(crate) fn get_beacon_execution_payload_envelope<T: BeaconChainTypes>(
eth_v1: EthV1Filter,
block_id_or_err: impl Filter<Extract = (BlockId,), Error = Rejection>
+ Clone
+ Send
+ Sync
+ 'static,
task_spawner_filter: TaskSpawnerFilter<T>,
chain_filter: ChainFilter<T>,
) -> ResponseFilter {
eth_v1
.and(warp::path("beacon"))
.and(warp::path("execution_payload_envelope"))
.and(block_id_or_err)
.and(warp::path::end())
.and(task_spawner_filter)
.and(chain_filter)
.and(warp::header::optional::<api_types::Accept>("accept"))
.then(
|block_id: BlockId,
task_spawner: TaskSpawner<T::EthSpec>,
chain: Arc<BeaconChain<T>>,
accept_header: Option<api_types::Accept>| {
task_spawner.blocking_response_task(Priority::P1, move || {
let (root, execution_optimistic, finalized) = block_id.root(&chain)?;

let envelope = chain
.get_payload_envelope(&root)
.map_err(warp_utils::reject::unhandled_error)?
.ok_or_else(|| {
warp_utils::reject::custom_not_found(format!(
"execution payload envelope for block root {root}"
))
})?;

let fork_name = chain
.spec
.fork_name_at_slot::<T::EthSpec>(envelope.message.slot);

match accept_header {
Some(api_types::Accept::Ssz) => Response::builder()
.status(200)
.body(envelope.as_ssz_bytes().into())
.map(|res: Response<Body>| add_ssz_content_type_header(res))
.map_err(|e| {
warp_utils::reject::custom_server_error(format!(
"failed to create response: {}",
e
))
}),
_ => {
let res = execution_optimistic_finalized_beacon_response(
ResponseIncludesVersion::Yes(fork_name),
execution_optimistic,
finalized,
&envelope,
)?;
Ok(warp::reply::json(&res).into_response())
}
}
.map(|resp| add_consensus_version_header(resp, fork_name))
})
},
)
.boxed()
}
12 changes: 11 additions & 1 deletion beacon_node/http_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ mod validators;
mod version;

use crate::beacon::execution_payload_envelope::{
post_beacon_execution_payload_envelope, post_beacon_execution_payload_envelope_ssz,
get_beacon_execution_payload_envelope, post_beacon_execution_payload_envelope,
post_beacon_execution_payload_envelope_ssz,
};
use crate::beacon::pool::*;
use crate::light_client::{get_light_client_bootstrap, get_light_client_updates};
Expand Down Expand Up @@ -1509,6 +1510,14 @@ pub fn serve<T: BeaconChainTypes>(
network_tx_filter.clone(),
);

// GET beacon/execution_payload_envelope/{block_id}
let get_beacon_execution_payload_envelope = get_beacon_execution_payload_envelope(
eth_v1.clone(),
block_id_or_err,
task_spawner_filter.clone(),
chain_filter.clone(),
);

let beacon_rewards_path = eth_v1
.clone()
.and(warp::path("beacon"))
Expand Down Expand Up @@ -3298,6 +3307,7 @@ pub fn serve<T: BeaconChainTypes>(
.uor(get_beacon_block_root)
.uor(get_blob_sidecars)
.uor(get_blobs)
.uor(get_beacon_execution_payload_envelope)
.uor(get_beacon_pool_attestations)
.uor(get_beacon_pool_attester_slashings)
.uor(get_beacon_pool_proposer_slashings)
Expand Down
49 changes: 49 additions & 0 deletions common/eth2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2732,6 +2732,55 @@ impl BeaconNodeHttpClient {
Ok(())
}

/// Path for `v1/beacon/execution_payload_envelope/{block_id}`
pub fn get_beacon_execution_payload_envelope_path(
&self,
block_id: BlockId,
) -> Result<Url, Error> {
let mut path = self.eth_path(V1)?;
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("beacon")
.push("execution_payload_envelope")
.push(&block_id.to_string());
Ok(path)
}

/// `GET v1/beacon/execution_payload_envelope/{block_id}`
///
/// Returns `Ok(None)` on a 404 error.
pub async fn get_beacon_execution_payload_envelope<E: EthSpec>(
&self,
block_id: BlockId,
) -> Result<
Option<ExecutionOptimisticFinalizedBeaconResponse<SignedExecutionPayloadEnvelope<E>>>,
Error,
> {
let path = self.get_beacon_execution_payload_envelope_path(block_id)?;
self.get_opt(path)
.await
.map(|opt| opt.map(BeaconResponse::ForkVersioned))
}

/// `GET v1/beacon/execution_payload_envelope/{block_id}` in SSZ format
///
/// Returns `Ok(None)` on a 404 error.
pub async fn get_beacon_execution_payload_envelope_ssz<E: EthSpec>(
&self,
block_id: BlockId,
) -> Result<Option<SignedExecutionPayloadEnvelope<E>>, Error> {
let path = self.get_beacon_execution_payload_envelope_path(block_id)?;
let opt_response = self
.get_bytes_opt_accept_header(path, Accept::Ssz, self.timeouts.get_beacon_blocks_ssz)
.await?;
match opt_response {
Some(bytes) => SignedExecutionPayloadEnvelope::from_ssz_bytes(&bytes)
.map(Some)
.map_err(Error::InvalidSsz),
None => Ok(None),
}
}

/// `GET v2/validator/blocks/{slot}` in ssz format
pub async fn get_validator_blocks_ssz<E: EthSpec>(
&self,
Expand Down
Loading