Allow HTTP API to return SSZ blocks (#2209)

## Issue Addressed

Implements https://github.com/ethereum/eth2.0-APIs/pull/125

## Proposed Changes

Optionally return SSZ bytes from the `beacon/blocks` endpoint.
This commit is contained in:
Michael Sproul 2021-02-24 04:15:14 +00:00
parent 5bc93869c8
commit 2f077b11fe
3 changed files with 56 additions and 9 deletions

View File

@ -872,11 +872,35 @@ pub fn serve<T: BeaconChainTypes>(
.and(chain_filter.clone()); .and(chain_filter.clone());
// GET beacon/blocks/{block_id} // GET beacon/blocks/{block_id}
let get_beacon_block = beacon_blocks_path.clone().and(warp::path::end()).and_then( let get_beacon_block = beacon_blocks_path
|block_id: BlockId, chain: Arc<BeaconChain<T>>| { .clone()
blocking_json_task(move || block_id.block(&chain).map(api_types::GenericResponse::from)) .and(warp::path::end())
}, .and(warp::header::optional::<api_types::Accept>("accept"))
); .and_then(
|block_id: BlockId,
chain: Arc<BeaconChain<T>>,
accept_header: Option<api_types::Accept>| {
blocking_task(move || {
let block = block_id.block(&chain)?;
match accept_header {
Some(api_types::Accept::Ssz) => Response::builder()
.status(200)
.header("Content-Type", "application/octet-stream")
.body(block.as_ssz_bytes().into())
.map_err(|e| {
warp_utils::reject::custom_server_error(format!(
"failed to create response: {}",
e
))
}),
_ => Ok(
warp::reply::json(&api_types::GenericResponseRef::from(&block))
.into_response(),
),
}
})
},
);
// GET beacon/blocks/{block_id}/root // GET beacon/blocks/{block_id}/root
let get_beacon_block_root = beacon_blocks_path let get_beacon_block_root = beacon_blocks_path

View File

@ -955,16 +955,18 @@ impl ApiTester {
pub async fn test_beacon_blocks(self) -> Self { pub async fn test_beacon_blocks(self) -> Self {
for block_id in self.interesting_block_ids() { for block_id in self.interesting_block_ids() {
let result = self let expected = self.get_block(block_id);
let json_result = self
.client .client
.get_beacon_blocks(block_id) .get_beacon_blocks(block_id)
.await .await
.unwrap() .unwrap()
.map(|res| res.data); .map(|res| res.data);
assert_eq!(json_result, expected, "{:?}", block_id);
let expected = self.get_block(block_id); let ssz_result = self.client.get_beacon_blocks_ssz(block_id).await.unwrap();
assert_eq!(ssz_result, expected, "{:?}", block_id);
assert_eq!(result, expected, "{:?}", block_id);
} }
self self

View File

@ -491,6 +491,27 @@ impl BeaconNodeHttpClient {
self.get_opt(path).await self.get_opt(path).await
} }
/// `GET beacon/blocks` as SSZ
///
/// Returns `Ok(None)` on a 404 error.
pub async fn get_beacon_blocks_ssz<T: EthSpec>(
&self,
block_id: BlockId,
) -> Result<Option<SignedBeaconBlock<T>>, Error> {
let mut path = self.eth_path()?;
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("beacon")
.push("blocks")
.push(&block_id.to_string());
self.get_bytes_opt_accept_header(path, Accept::Ssz)
.await?
.map(|bytes| SignedBeaconBlock::from_ssz_bytes(&bytes).map_err(Error::InvalidSsz))
.transpose()
}
/// `GET beacon/blocks/{block_id}/root` /// `GET beacon/blocks/{block_id}/root`
/// ///
/// Returns `Ok(None)` on a 404 error. /// Returns `Ok(None)` on a 404 error.