Properly Deserialize ForkVersionedResponses (#3944)

* Move ForkVersionedResponse to consensus/types

* Properly Deserialize ForkVersionedResponses

* Elide Types in from_value Calls

* Added Tests for ForkVersionedResponse Deserialize

* Address Sean's Comments & Make Less Restrictive

* Utilize `map_fork_name!`
This commit is contained in:
ethDreamer
2023-02-10 08:49:25 -06:00
committed by GitHub
parent e062a7cf76
commit 39f8327f73
12 changed files with 335 additions and 87 deletions

View File

@@ -14,9 +14,8 @@ pub mod lighthouse_vc;
pub mod mixin;
pub mod types;
use self::mixin::{RequestAccept, ResponseForkName, ResponseOptional};
use self::mixin::{RequestAccept, ResponseOptional};
use self::types::{Error as ResponseError, *};
use ::types::map_fork_name_with;
use futures::Stream;
use futures_util::StreamExt;
use lighthouse_network::PeerId;
@@ -683,35 +682,7 @@ impl BeaconNodeHttpClient {
None => return Ok(None),
};
// If present, use the fork provided in the headers to decode the block. Gracefully handle
// missing and malformed fork names by falling back to regular deserialisation.
let (block, version, execution_optimistic) = match response.fork_name_from_header() {
Ok(Some(fork_name)) => {
let (data, (version, execution_optimistic)) =
map_fork_name_with!(fork_name, SignedBeaconBlock, {
let ExecutionOptimisticForkVersionedResponse {
version,
execution_optimistic,
data,
} = response.json().await?;
(data, (version, execution_optimistic))
});
(data, version, execution_optimistic)
}
Ok(None) | Err(_) => {
let ExecutionOptimisticForkVersionedResponse {
version,
execution_optimistic,
data,
} = response.json().await?;
(data, version, execution_optimistic)
}
};
Ok(Some(ExecutionOptimisticForkVersionedResponse {
version,
execution_optimistic,
data: block,
}))
Ok(Some(response.json().await?))
}
/// `GET v1/beacon/blinded_blocks/{block_id}`
@@ -728,35 +699,7 @@ impl BeaconNodeHttpClient {
None => return Ok(None),
};
// If present, use the fork provided in the headers to decode the block. Gracefully handle
// missing and malformed fork names by falling back to regular deserialisation.
let (block, version, execution_optimistic) = match response.fork_name_from_header() {
Ok(Some(fork_name)) => {
let (data, (version, execution_optimistic)) =
map_fork_name_with!(fork_name, SignedBlindedBeaconBlock, {
let ExecutionOptimisticForkVersionedResponse {
version,
execution_optimistic,
data,
} = response.json().await?;
(data, (version, execution_optimistic))
});
(data, version, execution_optimistic)
}
Ok(None) | Err(_) => {
let ExecutionOptimisticForkVersionedResponse {
version,
execution_optimistic,
data,
} = response.json().await?;
(data, version, execution_optimistic)
}
};
Ok(Some(ExecutionOptimisticForkVersionedResponse {
version,
execution_optimistic,
data: block,
}))
Ok(Some(response.json().await?))
}
/// `GET v1/beacon/blocks` (LEGACY)

View File

@@ -236,21 +236,6 @@ impl<'a, T: Serialize> From<&'a T> for GenericResponseRef<'a, T> {
}
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ExecutionOptimisticForkVersionedResponse<T> {
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<ForkName>,
pub execution_optimistic: Option<bool>,
pub data: T,
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ForkVersionedResponse<T> {
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<ForkName>,
pub data: T,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct RootData {
pub root: Hash256,
@@ -1128,6 +1113,30 @@ pub struct BlocksAndBlobs<T: EthSpec, Payload: AbstractExecPayload<T>> {
pub kzg_aggregate_proof: KzgProof,
}
impl<T: EthSpec, Payload: AbstractExecPayload<T>> ForkVersionDeserialize
for BlocksAndBlobs<T, Payload>
{
fn deserialize_by_fork<'de, D: serde::Deserializer<'de>>(
value: serde_json::value::Value,
fork_name: ForkName,
) -> Result<Self, D::Error> {
#[derive(Deserialize)]
#[serde(bound = "T: EthSpec")]
struct Helper<T: EthSpec> {
block: serde_json::Value,
blobs: Vec<Blob<T>>,
kzg_aggregate_proof: KzgProof,
}
let helper: Helper<T> = serde_json::from_value(value).map_err(serde::de::Error::custom)?;
Ok(Self {
block: BeaconBlock::deserialize_by_fork::<'de, D>(helper.block, fork_name)?,
blobs: helper.blobs,
kzg_aggregate_proof: helper.kzg_aggregate_proof,
})
}
}
#[cfg(test)]
mod tests {
use super::*;