mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-06 10:11:44 +00:00
Fix get_header JSON deserialization. (#8228)
#8224 Please list or describe the changes introduced by this PR. Co-Authored-By: Jimmy Chen <jchen.tc@gmail.com>
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1235,10 +1235,12 @@ dependencies = [
|
|||||||
"eth2",
|
"eth2",
|
||||||
"ethereum_ssz",
|
"ethereum_ssz",
|
||||||
"lighthouse_version",
|
"lighthouse_version",
|
||||||
|
"mockito",
|
||||||
"reqwest 0.11.27",
|
"reqwest 0.11.27",
|
||||||
"sensitive_url",
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -12,3 +12,7 @@ reqwest = { workspace = true }
|
|||||||
sensitive_url = { workspace = true }
|
sensitive_url = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
mockito = { workspace = true }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
|||||||
@@ -155,15 +155,7 @@ impl BuilderHttpClient {
|
|||||||
}
|
}
|
||||||
ContentType::Json => {
|
ContentType::Json => {
|
||||||
self.ssz_available.store(false, Ordering::SeqCst);
|
self.ssz_available.store(false, Ordering::SeqCst);
|
||||||
let mut de = serde_json::Deserializer::from_slice(&response_bytes);
|
serde_json::from_slice(&response_bytes).map_err(Error::InvalidJson)
|
||||||
let data =
|
|
||||||
T::context_deserialize(&mut de, fork_name).map_err(Error::InvalidJson)?;
|
|
||||||
|
|
||||||
Ok(ForkVersionedResponse {
|
|
||||||
version: fork_name,
|
|
||||||
metadata: EmptyMetadata {},
|
|
||||||
data,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,6 +538,12 @@ impl BuilderHttpClient {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use eth2::types::builder_bid::{BuilderBid, BuilderBidFulu};
|
||||||
|
use eth2::types::test_utils::{SeedableRng, TestRandom, XorShiftRng};
|
||||||
|
use eth2::types::{MainnetEthSpec, Signature};
|
||||||
|
use mockito::{Matcher, Server, ServerGuard};
|
||||||
|
|
||||||
|
type E = MainnetEthSpec;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_headers_no_panic() {
|
fn test_headers_no_panic() {
|
||||||
@@ -556,4 +554,146 @@ mod tests {
|
|||||||
assert!(HeaderValue::from_str(JSON_ACCEPT_VALUE).is_ok());
|
assert!(HeaderValue::from_str(JSON_ACCEPT_VALUE).is_ok());
|
||||||
assert!(HeaderValue::from_str(JSON_CONTENT_TYPE_HEADER).is_ok());
|
assert!(HeaderValue::from_str(JSON_CONTENT_TYPE_HEADER).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_builder_header_ssz_response() {
|
||||||
|
// Set up mock server
|
||||||
|
let mut server = Server::new_async().await;
|
||||||
|
let mock_response_body = fulu_signed_builder_bid();
|
||||||
|
mock_get_header_response(
|
||||||
|
&mut server,
|
||||||
|
Some("fulu"),
|
||||||
|
ContentType::Ssz,
|
||||||
|
mock_response_body.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let builder_client = BuilderHttpClient::new(
|
||||||
|
SensitiveUrl::from_str(&server.url()).unwrap(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let response = builder_client
|
||||||
|
.get_builder_header(
|
||||||
|
Slot::new(1),
|
||||||
|
ExecutionBlockHash::repeat_byte(1),
|
||||||
|
&PublicKeyBytes::empty(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("should succeed in get_builder_header")
|
||||||
|
.expect("should have response body");
|
||||||
|
|
||||||
|
assert_eq!(response, mock_response_body);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_builder_header_json_response() {
|
||||||
|
// Set up mock server
|
||||||
|
let mut server = Server::new_async().await;
|
||||||
|
let mock_response_body = fulu_signed_builder_bid();
|
||||||
|
mock_get_header_response(
|
||||||
|
&mut server,
|
||||||
|
None,
|
||||||
|
ContentType::Json,
|
||||||
|
mock_response_body.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let builder_client = BuilderHttpClient::new(
|
||||||
|
SensitiveUrl::from_str(&server.url()).unwrap(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let response = builder_client
|
||||||
|
.get_builder_header(
|
||||||
|
Slot::new(1),
|
||||||
|
ExecutionBlockHash::repeat_byte(1),
|
||||||
|
&PublicKeyBytes::empty(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("should succeed in get_builder_header")
|
||||||
|
.expect("should have response body");
|
||||||
|
|
||||||
|
assert_eq!(response, mock_response_body);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_get_builder_header_no_version_header_fallback_json() {
|
||||||
|
// Set up mock server
|
||||||
|
let mut server = Server::new_async().await;
|
||||||
|
let mock_response_body = fulu_signed_builder_bid();
|
||||||
|
mock_get_header_response(
|
||||||
|
&mut server,
|
||||||
|
Some("fulu"),
|
||||||
|
ContentType::Json,
|
||||||
|
mock_response_body.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let builder_client = BuilderHttpClient::new(
|
||||||
|
SensitiveUrl::from_str(&server.url()).unwrap(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let response = builder_client
|
||||||
|
.get_builder_header(
|
||||||
|
Slot::new(1),
|
||||||
|
ExecutionBlockHash::repeat_byte(1),
|
||||||
|
&PublicKeyBytes::empty(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("should succeed in get_builder_header")
|
||||||
|
.expect("should have response body");
|
||||||
|
|
||||||
|
assert_eq!(response, mock_response_body);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mock_get_header_response(
|
||||||
|
server: &mut ServerGuard,
|
||||||
|
header_version_opt: Option<&str>,
|
||||||
|
content_type: ContentType,
|
||||||
|
response_body: ForkVersionedResponse<SignedBuilderBid<E>>,
|
||||||
|
) {
|
||||||
|
let mut mock = server.mock(
|
||||||
|
"GET",
|
||||||
|
Matcher::Regex(r"^/eth/v1/builder/header/\d+/.+/.+$".to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(version) = header_version_opt {
|
||||||
|
mock = mock.with_header(CONSENSUS_VERSION_HEADER, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
match content_type {
|
||||||
|
ContentType::Json => {
|
||||||
|
mock = mock
|
||||||
|
.with_header(CONTENT_TYPE_HEADER, JSON_CONTENT_TYPE_HEADER)
|
||||||
|
.with_body(serde_json::to_string(&response_body).unwrap());
|
||||||
|
}
|
||||||
|
ContentType::Ssz => {
|
||||||
|
mock = mock
|
||||||
|
.with_header(CONTENT_TYPE_HEADER, SSZ_CONTENT_TYPE_HEADER)
|
||||||
|
.with_body(response_body.data.as_ssz_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mock.with_status(200).create();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fulu_signed_builder_bid() -> ForkVersionedResponse<SignedBuilderBid<E>> {
|
||||||
|
let rng = &mut XorShiftRng::from_seed([42; 16]);
|
||||||
|
ForkVersionedResponse {
|
||||||
|
version: ForkName::Fulu,
|
||||||
|
metadata: EmptyMetadata {},
|
||||||
|
data: SignedBuilderBid {
|
||||||
|
message: BuilderBid::Fulu(BuilderBidFulu::random_for_test(rng)),
|
||||||
|
signature: Signature::empty(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user