Skip to content

Commit c528b7b

Browse files
committed
Fix Deserialize Beacon Blocks
1 parent 51a3abb commit c528b7b

File tree

3 files changed

+90
-16
lines changed

3 files changed

+90
-16
lines changed

beacon_node/http_api/src/lib.rs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ use bytes::Bytes;
4747
use directory::DEFAULT_ROOT_DIR;
4848
use either::Either;
4949
use eth2::types::{
50-
self as api_types, BroadcastValidation, EndpointVersion, ForkChoice, ForkChoiceNode,
51-
LightClientUpdatesQuery, PublishBlockRequest, ValidatorBalancesRequestBody, ValidatorId,
52-
ValidatorStatus, ValidatorsRequestBody,
50+
self as api_types, BroadcastValidation, ContextDeserialize, EndpointVersion, ForkChoice,
51+
ForkChoiceNode, LightClientUpdatesQuery, PublishBlockRequest, ValidatorBalancesRequestBody,
52+
ValidatorId, ValidatorStatus, ValidatorsRequestBody,
5353
};
5454
use eth2::{CONSENSUS_VERSION_HEADER, CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER};
5555
use health_metrics::observe::Observe;
@@ -1420,21 +1420,31 @@ pub fn serve<T: BeaconChainTypes>(
14201420
.and(warp::path("beacon"))
14211421
.and(warp::path("blocks"))
14221422
.and(warp::path::end())
1423-
.and(warp_utils::json::json())
1423+
.and(warp::body::bytes())
1424+
.and(consensus_version_header_filter)
14241425
.and(task_spawner_filter.clone())
14251426
.and(chain_filter.clone())
14261427
.and(network_tx_filter.clone())
14271428
.and(network_globals.clone())
14281429
.then(
1429-
move |block_contents: PublishBlockRequest<T::EthSpec>,
1430+
move |block_bytes: Bytes,
1431+
consensus_version: ForkName,
14301432
task_spawner: TaskSpawner<T::EthSpec>,
14311433
chain: Arc<BeaconChain<T>>,
14321434
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
14331435
network_globals: Arc<NetworkGlobals<T::EthSpec>>| {
14341436
task_spawner.spawn_async_with_rejection(Priority::P0, async move {
1437+
let mut deserializer = serde_json::Deserializer::from_slice(&block_bytes);
1438+
let request = PublishBlockRequest::<T::EthSpec>::context_deserialize(
1439+
&mut deserializer,
1440+
consensus_version,
1441+
)
1442+
.map_err(|e| {
1443+
warp_utils::reject::custom_bad_request(format!("invalid JSON: {e:?}"))
1444+
})?;
14351445
publish_blocks::publish_block(
14361446
None,
1437-
ProvenancedBlock::local_from_publish_request(block_contents),
1447+
ProvenancedBlock::local_from_publish_request(request),
14381448
chain,
14391449
&network_tx,
14401450
BroadcastValidation::default(),
@@ -1490,22 +1500,33 @@ pub fn serve<T: BeaconChainTypes>(
14901500
.and(warp::path("blocks"))
14911501
.and(warp::query::<api_types::BroadcastValidationQuery>())
14921502
.and(warp::path::end())
1493-
.and(warp_utils::json::json())
1503+
.and(warp::body::bytes())
1504+
.and(consensus_version_header_filter)
14941505
.and(task_spawner_filter.clone())
14951506
.and(chain_filter.clone())
14961507
.and(network_tx_filter.clone())
14971508
.and(network_globals.clone())
14981509
.then(
14991510
move |validation_level: api_types::BroadcastValidationQuery,
1500-
block_contents: PublishBlockRequest<T::EthSpec>,
1511+
block_bytes: Bytes,
1512+
consensus_version: ForkName,
15011513
task_spawner: TaskSpawner<T::EthSpec>,
15021514
chain: Arc<BeaconChain<T>>,
15031515
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
15041516
network_globals: Arc<NetworkGlobals<T::EthSpec>>| {
15051517
task_spawner.spawn_async_with_rejection(Priority::P0, async move {
1518+
let mut deserializer = serde_json::Deserializer::from_slice(&block_bytes);
1519+
let request = PublishBlockRequest::<T::EthSpec>::context_deserialize(
1520+
&mut deserializer,
1521+
consensus_version,
1522+
)
1523+
.map_err(|e| {
1524+
warp_utils::reject::custom_bad_request(format!("invalid JSON: {e:?}"))
1525+
})?;
1526+
15061527
publish_blocks::publish_block(
15071528
None,
1508-
ProvenancedBlock::local_from_publish_request(block_contents),
1529+
ProvenancedBlock::local_from_publish_request(request),
15091530
chain,
15101531
&network_tx,
15111532
validation_level.broadcast_validation,

common/eth2/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,8 +1041,14 @@ impl BeaconNodeHttpClient {
10411041
.push("beacon")
10421042
.push("blocks");
10431043

1044-
self.post_with_timeout(path, block_contents, self.timeouts.proposal)
1045-
.await?;
1044+
let fork_name = block_contents.signed_block().fork_name_unchecked();
1045+
self.post_generic_with_consensus_version(
1046+
path,
1047+
block_contents,
1048+
Some(self.timeouts.proposal),
1049+
fork_name,
1050+
)
1051+
.await?;
10461052

10471053
Ok(())
10481054
}

common/eth2/src/types.rs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,7 +1603,7 @@ mod tests {
16031603
}
16041604
}
16051605

1606-
#[derive(Debug, Encode, Serialize, Deserialize)]
1606+
#[derive(Debug, Encode, Serialize)]
16071607
#[serde(untagged)]
16081608
#[serde(bound = "E: EthSpec")]
16091609
#[ssz(enum_behaviour = "transparent")]
@@ -1616,7 +1616,7 @@ pub type JsonProduceBlockV3Response<E> =
16161616
ForkVersionedResponse<ProduceBlockV3Response<E>, ProduceBlockV3Metadata>;
16171617

16181618
/// A wrapper over a [`BeaconBlock`] or a [`BlockContents`].
1619-
#[derive(Debug, Encode, Serialize, Deserialize)]
1619+
#[derive(Debug, Encode, Serialize)]
16201620
#[serde(untagged)]
16211621
#[serde(bound = "E: EthSpec")]
16221622
#[ssz(enum_behaviour = "transparent")]
@@ -1808,7 +1808,7 @@ impl TryFrom<&HeaderMap> for ProduceBlockV3Metadata {
18081808
}
18091809

18101810
/// A wrapper over a [`SignedBeaconBlock`] or a [`SignedBlockContents`].
1811-
#[derive(Clone, Debug, Encode, Serialize, Deserialize)]
1811+
#[derive(Clone, Debug, Encode, Serialize)]
18121812
#[serde(untagged)]
18131813
#[serde(bound = "E: EthSpec")]
18141814
#[ssz(enum_behaviour = "transparent")]
@@ -1817,6 +1817,28 @@ pub enum PublishBlockRequest<E: EthSpec> {
18171817
Block(Arc<SignedBeaconBlock<E>>),
18181818
}
18191819

1820+
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for PublishBlockRequest<E> {
1821+
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
1822+
where
1823+
D: Deserializer<'de>,
1824+
{
1825+
let value = serde_json::Value::deserialize(deserializer)?;
1826+
1827+
if let Ok(contents) = SignedBlockContents::<E>::context_deserialize(value.clone(), context)
1828+
{
1829+
return Ok(PublishBlockRequest::BlockContents(contents));
1830+
}
1831+
1832+
if let Ok(block) = Arc::<SignedBeaconBlock<E>>::context_deserialize(value, context) {
1833+
return Ok(PublishBlockRequest::Block(block));
1834+
}
1835+
1836+
Err(serde::de::Error::custom(
1837+
"could not match any variant of PublishBlockRequest",
1838+
))
1839+
}
1840+
}
1841+
18201842
impl<E: EthSpec> PublishBlockRequest<E> {
18211843
pub fn new(
18221844
block: Arc<SignedBeaconBlock<E>>,
@@ -1893,7 +1915,7 @@ impl<E: EthSpec> From<SignedBlockContentsTuple<E>> for PublishBlockRequest<E> {
18931915
}
18941916
}
18951917

1896-
#[derive(Debug, Clone, Serialize, Deserialize, Encode)]
1918+
#[derive(Debug, Clone, Serialize, Encode)]
18971919
#[serde(bound = "E: EthSpec")]
18981920
pub struct SignedBlockContents<E: EthSpec> {
18991921
pub signed_block: Arc<SignedBeaconBlock<E>>,
@@ -1902,7 +1924,32 @@ pub struct SignedBlockContents<E: EthSpec> {
19021924
pub blobs: BlobsList<E>,
19031925
}
19041926

1905-
#[derive(Debug, Clone, Serialize, Deserialize, Encode)]
1927+
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for SignedBlockContents<E> {
1928+
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
1929+
where
1930+
D: Deserializer<'de>,
1931+
{
1932+
#[derive(Deserialize)]
1933+
#[serde(bound = "E: EthSpec")]
1934+
struct Helper<E: EthSpec> {
1935+
signed_block: serde_json::Value,
1936+
kzg_proofs: KzgProofs<E>,
1937+
blobs: BlobsList<E>,
1938+
}
1939+
let helper = Helper::<E>::deserialize(deserializer).map_err(serde::de::Error::custom)?;
1940+
1941+
let block = SignedBeaconBlock::context_deserialize(helper.signed_block, context)
1942+
.map_err(serde::de::Error::custom)?;
1943+
1944+
Ok(Self {
1945+
signed_block: Arc::new(block),
1946+
kzg_proofs: helper.kzg_proofs,
1947+
blobs: helper.blobs,
1948+
})
1949+
}
1950+
}
1951+
1952+
#[derive(Debug, Clone, Serialize, Encode)]
19061953
#[serde(bound = "E: EthSpec")]
19071954
pub struct BlockContents<E: EthSpec> {
19081955
pub block: BeaconBlock<E>,

0 commit comments

Comments
 (0)