mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 00:42:42 +00:00
Gloas get payload envelope beacon API (#9038)
Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com> Co-Authored-By: Mac L <mjladson@pm.me>
This commit is contained in:
@@ -1,16 +1,25 @@
|
|||||||
|
use crate::block_id::BlockId;
|
||||||
use crate::task_spawner::{Priority, TaskSpawner};
|
use crate::task_spawner::{Priority, TaskSpawner};
|
||||||
use crate::utils::{ChainFilter, EthV1Filter, NetworkTxFilter, ResponseFilter, TaskSpawnerFilter};
|
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 beacon_chain::{BeaconChain, BeaconChainTypes};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
use eth2::types as api_types;
|
||||||
use eth2::{CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER};
|
use eth2::{CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER};
|
||||||
use lighthouse_network::PubsubMessage;
|
use lighthouse_network::PubsubMessage;
|
||||||
use network::NetworkMessage;
|
use network::NetworkMessage;
|
||||||
use ssz::Decode;
|
use ssz::{Decode, Encode};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
use types::SignedExecutionPayloadEnvelope;
|
use types::SignedExecutionPayloadEnvelope;
|
||||||
use warp::{Filter, Rejection, Reply, reply::Response};
|
use warp::{
|
||||||
|
Filter, Rejection, Reply,
|
||||||
|
hyper::{Body, Response},
|
||||||
|
};
|
||||||
|
|
||||||
// POST beacon/execution_payload_envelope (SSZ)
|
// POST beacon/execution_payload_envelope (SSZ)
|
||||||
pub(crate) fn post_beacon_execution_payload_envelope_ssz<T: BeaconChainTypes>(
|
pub(crate) fn post_beacon_execution_payload_envelope_ssz<T: BeaconChainTypes>(
|
||||||
@@ -81,7 +90,7 @@ pub async fn publish_execution_payload_envelope<T: BeaconChainTypes>(
|
|||||||
envelope: SignedExecutionPayloadEnvelope<T::EthSpec>,
|
envelope: SignedExecutionPayloadEnvelope<T::EthSpec>,
|
||||||
chain: Arc<BeaconChain<T>>,
|
chain: Arc<BeaconChain<T>>,
|
||||||
network_tx: &UnboundedSender<NetworkMessage<T::EthSpec>>,
|
network_tx: &UnboundedSender<NetworkMessage<T::EthSpec>>,
|
||||||
) -> Result<Response, Rejection> {
|
) -> Result<Response<Body>, Rejection> {
|
||||||
let slot = envelope.message.slot;
|
let slot = envelope.message.slot;
|
||||||
let beacon_block_root = envelope.message.beacon_block_root;
|
let beacon_block_root = envelope.message.beacon_block_root;
|
||||||
|
|
||||||
@@ -114,3 +123,72 @@ pub async fn publish_execution_payload_envelope<T: BeaconChainTypes>(
|
|||||||
|
|
||||||
Ok(warp::reply().into_response())
|
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()
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ mod validators;
|
|||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
use crate::beacon::execution_payload_envelope::{
|
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::beacon::pool::*;
|
||||||
use crate::light_client::{get_light_client_bootstrap, get_light_client_updates};
|
use crate::light_client::{get_light_client_bootstrap, get_light_client_updates};
|
||||||
@@ -1509,6 +1510,14 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
network_tx_filter.clone(),
|
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
|
let beacon_rewards_path = eth_v1
|
||||||
.clone()
|
.clone()
|
||||||
.and(warp::path("beacon"))
|
.and(warp::path("beacon"))
|
||||||
@@ -3298,6 +3307,7 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
.uor(get_beacon_block_root)
|
.uor(get_beacon_block_root)
|
||||||
.uor(get_blob_sidecars)
|
.uor(get_blob_sidecars)
|
||||||
.uor(get_blobs)
|
.uor(get_blobs)
|
||||||
|
.uor(get_beacon_execution_payload_envelope)
|
||||||
.uor(get_beacon_pool_attestations)
|
.uor(get_beacon_pool_attestations)
|
||||||
.uor(get_beacon_pool_attester_slashings)
|
.uor(get_beacon_pool_attester_slashings)
|
||||||
.uor(get_beacon_pool_proposer_slashings)
|
.uor(get_beacon_pool_proposer_slashings)
|
||||||
|
|||||||
@@ -2732,6 +2732,55 @@ impl BeaconNodeHttpClient {
|
|||||||
Ok(())
|
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
|
/// `GET v2/validator/blocks/{slot}` in ssz format
|
||||||
pub async fn get_validator_blocks_ssz<E: EthSpec>(
|
pub async fn get_validator_blocks_ssz<E: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
Reference in New Issue
Block a user