Skip to content

Commit

Permalink
add ssz support in request body for /beacon/blocks endpoints (v1 & v2) (
Browse files Browse the repository at this point in the history
sigp#4479)

[sigp#4457](sigp#4457)

add ssz support in request body for  /beacon/blocks endpoints (v1 & v2)
  • Loading branch information
eserilev authored and Woodpile37 committed Jan 6, 2024
1 parent 2403f0e commit d4b276b
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions beacon_node/http_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ operation_pool = { path = "../operation_pool" }
sensitive_url = { path = "../../common/sensitive_url" }
unused_port = {path = "../../common/unused_port"}
store = { path = "../store" }
bytes = "1.1.0"

[dev-dependencies]
environment = { path = "../../lighthouse/environment" }
Expand Down
42 changes: 42 additions & 0 deletions beacon_node/http_api/tests/broadcast_validation_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,48 @@ pub async fn gossip_full_pass() {
.block_is_known_to_fork_choice(&block.canonical_root()));
}

// This test checks that a block that is valid from both a gossip and consensus perspective is accepted when using `broadcast_validation=gossip`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
pub async fn gossip_full_pass_ssz() {
/* this test targets gossip-level validation */
let validation_level: Option<BroadcastValidation> = Some(BroadcastValidation::Gossip);

// Validator count needs to be at least 32 or proposer boost gets set to 0 when computing
// `validator_count // 32`.
let validator_count = 64;
let num_initial: u64 = 31;
let tester = InteractiveTester::<E>::new(None, validator_count).await;

// Create some chain depth.
tester.harness.advance_slot();
tester
.harness
.extend_chain(
num_initial as usize,
BlockStrategy::OnCanonicalHead,
AttestationStrategy::AllValidators,
)
.await;
tester.harness.advance_slot();

let slot_a = Slot::new(num_initial);
let slot_b = slot_a + 1;

let state_a = tester.harness.get_current_state();
let (block, _): (SignedBeaconBlock<E>, _) = tester.harness.make_block(state_a, slot_b).await;

let response: Result<(), eth2::Error> = tester
.client
.post_beacon_blocks_v2_ssz(&block, validation_level)
.await;

assert!(response.is_ok());
assert!(tester
.harness
.chain
.block_is_known_to_fork_choice(&block.canonical_root()));
}

/// This test checks that a block that is **invalid** from a gossip perspective gets rejected when using `broadcast_validation=consensus`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
pub async fn consensus_invalid() {
Expand Down
55 changes: 55 additions & 0 deletions beacon_node/http_api/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,22 @@ impl ApiTester {
self
}

pub async fn test_post_beacon_blocks_ssz_valid(mut self) -> Self {
let next_block = &self.next_block;

self.client
.post_beacon_blocks_ssz(next_block)
.await
.unwrap();

assert!(
self.network_rx.network_recv.recv().await.is_some(),
"valid blocks should be sent to network"
);

self
}

pub async fn test_post_beacon_blocks_invalid(mut self) -> Self {
let block = self
.harness
Expand All @@ -1270,6 +1286,29 @@ impl ApiTester {
self
}

pub async fn test_post_beacon_blocks_ssz_invalid(mut self) -> Self {
let block = self
.harness
.make_block_with_modifier(
self.harness.get_current_state(),
self.harness.get_current_slot(),
|b| {
*b.state_root_mut() = Hash256::zero();
},
)
.await
.0;

assert!(self.client.post_beacon_blocks_ssz(&block).await.is_err());

assert!(
self.network_rx.network_recv.recv().await.is_some(),
"gossip valid blocks should be sent to network"
);

self
}

pub async fn test_beacon_blocks(self) -> Self {
for block_id in self.interesting_block_ids() {
let expected = block_id
Expand Down Expand Up @@ -4451,6 +4490,22 @@ async fn post_beacon_blocks_valid() {
ApiTester::new().await.test_post_beacon_blocks_valid().await;
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_beacon_blocks_ssz_valid() {
ApiTester::new()
.await
.test_post_beacon_blocks_ssz_valid()
.await;
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_post_beacon_blocks_ssz_invalid() {
ApiTester::new()
.await
.test_post_beacon_blocks_ssz_invalid()
.await;
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_beacon_blocks_invalid() {
ApiTester::new()
Expand Down
87 changes: 86 additions & 1 deletion common/eth2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ use futures_util::StreamExt;
use lighthouse_network::PeerId;
use pretty_reqwest_error::PrettyReqwestError;
pub use reqwest;
use reqwest::{IntoUrl, RequestBuilder, Response};
use reqwest::{
header::{HeaderMap, HeaderValue},
Body, IntoUrl, RequestBuilder, Response,
};
pub use reqwest::{StatusCode, Url};
pub use sensitive_url::{SensitiveError, SensitiveUrl};
use serde::{de::DeserializeOwned, Serialize};
use ssz::Encode;
use std::convert::TryFrom;
use std::fmt;
use std::iter::Iterator;
Expand Down Expand Up @@ -322,6 +326,25 @@ impl BeaconNodeHttpClient {
ok_or_error(response).await
}

/// Generic POST function supporting arbitrary responses and timeouts.
async fn post_generic_with_ssz_body<T: Into<Body>, U: IntoUrl>(
&self,
url: U,
body: T,
timeout: Option<Duration>,
) -> Result<Response, Error> {
let mut builder = self.client.post(url);
if let Some(timeout) = timeout {
builder = builder.timeout(timeout);
}
let response = builder
.header("Content-Type", "application/octet-stream")
.body(body)
.send()
.await?;
ok_or_error(response).await
}

/// Generic POST function supporting arbitrary responses and timeouts.
async fn post_generic_with_consensus_version<T: Serialize, U: IntoUrl>(
&self,
Expand All @@ -342,6 +365,31 @@ impl BeaconNodeHttpClient {
ok_or_error(response).await
}

/// Generic POST function supporting arbitrary responses and timeouts.
async fn post_generic_with_consensus_version_and_ssz_body<T: Into<Body>, U: IntoUrl>(
&self,
url: U,
body: T,
timeout: Option<Duration>,
fork: ForkName,
) -> Result<Response, Error> {
let mut builder = self.client.post(url);
if let Some(timeout) = timeout {
builder = builder.timeout(timeout);
}
let mut headers = HeaderMap::new();
headers.insert(
CONSENSUS_VERSION_HEADER,
HeaderValue::from_str(&fork.to_string()).expect("Failed to create header value"),
);
headers.insert(
"Content-Type",
HeaderValue::from_static("application/octet-stream"),
);
let response = builder.headers(headers).body(body).send().await?;
ok_or_error(response).await
}

/// `GET beacon/genesis`
///
/// ## Errors
Expand Down Expand Up @@ -654,6 +702,26 @@ impl BeaconNodeHttpClient {
Ok(())
}

/// `POST beacon/blocks`
///
/// Returns `Ok(None)` on a 404 error.
pub async fn post_beacon_blocks_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
&self,
block: &SignedBeaconBlock<T, Payload>,
) -> Result<(), Error> {
let mut path = self.eth_path(V1)?;

path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("beacon")
.push("blocks");

self.post_generic_with_ssz_body(path, block.as_ssz_bytes(), Some(self.timeouts.proposal))
.await?;

Ok(())
}

/// `POST beacon/blinded_blocks`
///
/// Returns `Ok(None)` on a 404 error.
Expand Down Expand Up @@ -727,6 +795,23 @@ impl BeaconNodeHttpClient {
Ok(())
}

/// `POST v2/beacon/blocks`
pub async fn post_beacon_blocks_v2_ssz<T: EthSpec, Payload: AbstractExecPayload<T>>(
&self,
block: &SignedBeaconBlock<T, Payload>,
validation_level: Option<BroadcastValidation>,
) -> Result<(), Error> {
self.post_generic_with_consensus_version_and_ssz_body(
self.post_beacon_blocks_v2_path(validation_level)?,
block.as_ssz_bytes(),
Some(self.timeouts.proposal),
block.message().body().fork_name(),
)
.await?;

Ok(())
}

/// `POST v2/beacon/blinded_blocks`
pub async fn post_beacon_blinded_blocks_v2<T: EthSpec>(
&self,
Expand Down

0 comments on commit d4b276b

Please sign in to comment.