Resolve merge conflicts

This commit is contained in:
Eitan Seri-Levi
2026-01-02 08:52:14 -06:00
918 changed files with 49304 additions and 37273 deletions

View File

@@ -1,54 +1,57 @@
#![cfg(test)]
use lighthouse_network::service::Network as LibP2PService;
use fixed_bytes::FixedBytesExtended;
use lighthouse_network::Enr;
use lighthouse_network::EnrExt;
use lighthouse_network::Multiaddr;
use lighthouse_network::service::Network as LibP2PService;
use lighthouse_network::{NetworkConfig, NetworkEvent};
use network_utils::enr_ext::EnrExt;
use std::sync::Arc;
use std::sync::Weak;
use tokio::runtime::Runtime;
use tracing::{debug, error, info_span, Instrument};
use tracing::{Instrument, debug, error, info_span};
use tracing_subscriber::EnvFilter;
use types::{
ChainSpec, EnrForkId, Epoch, EthSpec, FixedBytesExtended, ForkContext, ForkName, Hash256,
MinimalEthSpec, Slot,
};
use types::{ChainSpec, EnrForkId, Epoch, EthSpec, ForkContext, ForkName, Hash256, MinimalEthSpec};
type E = MinimalEthSpec;
use lighthouse_network::identity::secp256k1;
use lighthouse_network::rpc::config::InboundRateLimiterConfig;
use tempfile::Builder as TempBuilder;
/// Returns a dummy fork context
pub fn fork_context(fork_name: ForkName) -> ForkContext {
/// Returns a chain spec with all forks enabled.
pub fn spec_with_all_forks_enabled() -> ChainSpec {
let mut chain_spec = E::default_spec();
let altair_fork_epoch = Epoch::new(1);
let bellatrix_fork_epoch = Epoch::new(2);
let capella_fork_epoch = Epoch::new(3);
let deneb_fork_epoch = Epoch::new(4);
let electra_fork_epoch = Epoch::new(5);
let eip7805_fork_epoch = Epoch::new(6);
let fulu_fork_epoch = Epoch::new(7);
chain_spec.altair_fork_epoch = Some(Epoch::new(1));
chain_spec.bellatrix_fork_epoch = Some(Epoch::new(2));
chain_spec.capella_fork_epoch = Some(Epoch::new(3));
chain_spec.deneb_fork_epoch = Some(Epoch::new(4));
chain_spec.electra_fork_epoch = Some(Epoch::new(5));
chain_spec.fulu_fork_epoch = Some(Epoch::new(6));
chain_spec.eip7805_fork_epoch = Some(Epoch::new(7));
chain_spec.gloas_fork_epoch = Some(Epoch::new(8));
chain_spec.altair_fork_epoch = Some(altair_fork_epoch);
chain_spec.bellatrix_fork_epoch = Some(bellatrix_fork_epoch);
chain_spec.capella_fork_epoch = Some(capella_fork_epoch);
chain_spec.deneb_fork_epoch = Some(deneb_fork_epoch);
chain_spec.electra_fork_epoch = Some(electra_fork_epoch);
chain_spec.eip7805_fork_epoch = Some(eip7805_fork_epoch);
chain_spec.fulu_fork_epoch = Some(fulu_fork_epoch);
// check that we have all forks covered
assert!(chain_spec.fork_epoch(ForkName::latest()).is_some());
chain_spec
}
let current_slot = match fork_name {
ForkName::Base => Slot::new(0),
ForkName::Altair => altair_fork_epoch.start_slot(E::slots_per_epoch()),
ForkName::Bellatrix => bellatrix_fork_epoch.start_slot(E::slots_per_epoch()),
ForkName::Capella => capella_fork_epoch.start_slot(E::slots_per_epoch()),
ForkName::Deneb => deneb_fork_epoch.start_slot(E::slots_per_epoch()),
ForkName::Electra => electra_fork_epoch.start_slot(E::slots_per_epoch()),
ForkName::Eip7805 => eip7805_fork_epoch.start_slot(E::slots_per_epoch()),
ForkName::Fulu => fulu_fork_epoch.start_slot(E::slots_per_epoch()),
/// Returns a dummy fork context
pub fn fork_context(fork_name: ForkName, spec: &ChainSpec) -> ForkContext {
let current_epoch = match fork_name {
ForkName::Base => Some(Epoch::new(0)),
ForkName::Altair => spec.altair_fork_epoch,
ForkName::Bellatrix => spec.bellatrix_fork_epoch,
ForkName::Capella => spec.capella_fork_epoch,
ForkName::Deneb => spec.deneb_fork_epoch,
ForkName::Electra => spec.electra_fork_epoch,
ForkName::Fulu => spec.fulu_fork_epoch,
ForkName::Eip7805 => spec.eip7805_fork_epoch,
ForkName::Gloas => spec.gloas_fork_epoch,
};
ForkContext::new::<E>(current_slot, Hash256::zero(), &chain_spec)
let current_slot = current_epoch
.unwrap_or_else(|| panic!("expect fork {fork_name} to be scheduled"))
.start_slot(E::slots_per_epoch());
ForkContext::new::<E>(current_slot, Hash256::zero(), spec)
}
pub struct Libp2pInstance(
@@ -72,12 +75,18 @@ impl std::ops::DerefMut for Libp2pInstance {
}
#[allow(unused)]
pub fn build_tracing_subscriber(level: &str, enabled: bool) {
pub fn build_tracing_subscriber(
level: &str,
enabled: bool,
) -> Option<tracing::subscriber::DefaultGuard> {
if enabled {
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::try_new(level).unwrap())
.try_init()
.unwrap();
Some(tracing::subscriber::set_default(
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::try_new(level).unwrap())
.finish(),
))
} else {
None
}
}
@@ -100,7 +109,7 @@ pub fn build_config(
config.set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, port, port, port);
config.enr_address = (Some(std::net::Ipv4Addr::LOCALHOST), None);
config.boot_nodes_enr.append(&mut boot_nodes);
config.network_dir = path.into_path();
config.network_dir = path.keep();
config.disable_peer_scoring = disable_peer_scoring;
config.inbound_rate_limiter_config = inbound_rate_limiter;
Arc::new(config)
@@ -121,18 +130,24 @@ pub async fn build_libp2p_instance(
let (signal, exit) = async_channel::bounded(1);
let (shutdown_tx, _) = futures::channel::mpsc::channel(1);
let executor = task_executor::TaskExecutor::new(rt, exit, shutdown_tx, service_name);
let custody_group_count = chain_spec.custody_requirement;
let libp2p_context = lighthouse_network::Context {
config,
enr_fork_id: EnrForkId::default(),
fork_context: Arc::new(fork_context(fork_name)),
fork_context: Arc::new(fork_context(fork_name, &chain_spec)),
chain_spec,
libp2p_registry: None,
};
Libp2pInstance(
LibP2PService::new(executor, libp2p_context)
.await
.expect("should build libp2p instance")
.0,
LibP2PService::new(
executor,
libp2p_context,
custody_group_count,
secp256k1::Keypair::generate().into(),
)
.await
.expect("should build libp2p instance")
.0,
signal,
)
}

View File

@@ -0,0 +1,2 @@
mod common;
mod rpc_tests;

View File

@@ -1,22 +1,25 @@
#![cfg(test)]
mod common;
use common::{build_tracing_subscriber, Protocol};
use lighthouse_network::rpc::{methods::*, RequestType};
use crate::common;
use crate::common::spec_with_all_forks_enabled;
use crate::common::{Protocol, build_tracing_subscriber};
use bls::Signature;
use fixed_bytes::FixedBytesExtended;
use lighthouse_network::rpc::{RequestType, methods::*};
use lighthouse_network::service::api_types::AppRequestId;
use lighthouse_network::{NetworkEvent, ReportSource, Response};
use ssz::Encode;
use ssz_types::VariableList;
use ssz_types::{RuntimeVariableList, VariableList};
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::runtime::Runtime;
use tokio::time::sleep;
use tracing::{debug, error, warn};
use tracing::{Instrument, debug, error, info_span, warn};
use types::{
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BlobSidecar, ChainSpec,
EmptyBlock, Epoch, EthSpec, FixedBytesExtended, ForkName, Hash256, MinimalEthSpec,
RuntimeVariableList, Signature, SignedBeaconBlock, Slot,
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BeaconBlockHeader,
BlobSidecar, ChainSpec, DataColumnSidecar, DataColumnsByRootIdentifier, EmptyBlock, Epoch,
EthSpec, ForkName, Hash256, KzgCommitment, KzgProof, MinimalEthSpec, SignedBeaconBlock,
SignedBeaconBlockHeader, Slot,
};
type E = MinimalEthSpec;
@@ -24,8 +27,8 @@ type E = MinimalEthSpec;
/// Bellatrix block with length < max_rpc_size.
fn bellatrix_block_small(spec: &ChainSpec) -> BeaconBlock<E> {
let mut block = BeaconBlockBellatrix::<E>::empty(spec);
let tx = VariableList::from(vec![0; 1024]);
let txs = VariableList::from(std::iter::repeat_n(tx, 5000).collect::<Vec<_>>());
let tx = VariableList::try_from(vec![0; 1024]).unwrap();
let txs = VariableList::try_from(std::iter::repeat_n(tx, 5000).collect::<Vec<_>>()).unwrap();
block.body.execution_payload.execution_payload.transactions = txs;
@@ -39,8 +42,8 @@ fn bellatrix_block_small(spec: &ChainSpec) -> BeaconBlock<E> {
/// Hence, we generate a bellatrix block just greater than `MAX_RPC_SIZE` to test rejection on the rpc layer.
fn bellatrix_block_large(spec: &ChainSpec) -> BeaconBlock<E> {
let mut block = BeaconBlockBellatrix::<E>::empty(spec);
let tx = VariableList::from(vec![0; 1024]);
let txs = VariableList::from(std::iter::repeat_n(tx, 100000).collect::<Vec<_>>());
let tx = VariableList::try_from(vec![0; 1024]).unwrap();
let txs = VariableList::try_from(std::iter::repeat_n(tx, 100000).collect::<Vec<_>>()).unwrap();
block.body.execution_payload.execution_payload.transactions = txs;
@@ -55,12 +58,12 @@ fn bellatrix_block_large(spec: &ChainSpec) -> BeaconBlock<E> {
fn test_tcp_status_rpc() {
// Set up the logging.
let log_level = "debug";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
rt.block_on(async {
// get sender/receiver
@@ -75,22 +78,24 @@ fn test_tcp_status_rpc() {
.await;
// Dummy STATUS RPC message
let rpc_request = RequestType::Status(StatusMessage {
let rpc_request = RequestType::Status(StatusMessage::V2(StatusMessageV2 {
fork_digest: [0; 4],
finalized_root: Hash256::zero(),
finalized_epoch: Epoch::new(1),
head_root: Hash256::zero(),
head_slot: Slot::new(1),
});
earliest_available_slot: Slot::new(0),
}));
// Dummy STATUS RPC message
let rpc_response = Response::Status(StatusMessage {
let rpc_response = Response::Status(StatusMessage::V2(StatusMessageV2 {
fork_digest: [0; 4],
finalized_root: Hash256::zero(),
finalized_epoch: Epoch::new(1),
head_root: Hash256::zero(),
head_slot: Slot::new(1),
});
earliest_available_slot: Slot::new(0),
}));
// build the sender future
let sender_future = async {
@@ -117,7 +122,8 @@ fn test_tcp_status_rpc() {
_ => {}
}
}
};
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
@@ -141,7 +147,8 @@ fn test_tcp_status_rpc() {
_ => {} // Ignore other events
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
@@ -159,14 +166,14 @@ fn test_tcp_status_rpc() {
fn test_tcp_blocks_by_range_chunked_rpc() {
// Set up the logging.
let log_level = "debug";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let messages_to_send = 6;
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
rt.block_on(async {
// get sender/receiver
@@ -245,7 +252,8 @@ fn test_tcp_blocks_by_range_chunked_rpc() {
_ => {} // Ignore other behaviour events
}
}
};
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
@@ -286,7 +294,8 @@ fn test_tcp_blocks_by_range_chunked_rpc() {
_ => {} // Ignore other events
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
@@ -304,8 +313,8 @@ fn test_tcp_blocks_by_range_chunked_rpc() {
fn test_blobs_by_range_chunked_rpc() {
// Set up the logging.
let log_level = "debug";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let slot_count = 32;
let messages_to_send = 34;
@@ -314,7 +323,7 @@ fn test_blobs_by_range_chunked_rpc() {
rt.block_on(async {
// get sender/receiver
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
let (mut sender, mut receiver) = common::build_node_pair(
Arc::downgrade(&rt),
ForkName::Deneb,
@@ -326,13 +335,18 @@ fn test_blobs_by_range_chunked_rpc() {
.await;
// BlobsByRange Request
let deneb_slot = spec
.deneb_fork_epoch
.expect("deneb must be scheduled")
.start_slot(E::slots_per_epoch());
let rpc_request = RequestType::BlobsByRange(BlobsByRangeRequest {
start_slot: 0,
start_slot: deneb_slot.as_u64(),
count: slot_count,
});
// BlocksByRange Response
let blob = BlobSidecar::<E>::empty();
// BlobsByRange Response
let mut blob = BlobSidecar::<E>::empty();
blob.signed_block_header.message.slot = deneb_slot;
let rpc_response = Response::BlobsByRange(Some(Arc::new(blob)));
@@ -373,7 +387,8 @@ fn test_blobs_by_range_chunked_rpc() {
_ => {} // Ignore other behaviour events
}
}
};
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
@@ -407,7 +422,8 @@ fn test_blobs_by_range_chunked_rpc() {
_ => {} // Ignore other events
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
@@ -425,14 +441,14 @@ fn test_blobs_by_range_chunked_rpc() {
fn test_tcp_blocks_by_range_over_limit() {
// Set up the logging.
let log_level = "debug";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let messages_to_send = 5;
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
rt.block_on(async {
// get sender/receiver
@@ -479,7 +495,8 @@ fn test_tcp_blocks_by_range_over_limit() {
_ => {} // Ignore other behaviour events
}
}
};
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
@@ -512,7 +529,8 @@ fn test_tcp_blocks_by_range_over_limit() {
_ => {} // Ignore other events
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
@@ -529,15 +547,15 @@ fn test_tcp_blocks_by_range_over_limit() {
fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() {
// Set up the logging.
let log_level = "debug";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let messages_to_send = 10;
let extra_messages_to_send = 10;
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
rt.block_on(async {
// get sender/receiver
@@ -601,7 +619,8 @@ fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() {
_ => {} // Ignore other behaviour events
}
}
};
}
.instrument(info_span!("Sender"));
// determine messages to send (PeerId, RequestId). If some, indicates we still need to send
// messages
@@ -637,9 +656,8 @@ fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() {
}
// if we need to send messages send them here. This will happen after a delay
if message_info.is_some() {
if let Some((peer_id, inbound_request_id)) = &message_info {
messages_sent += 1;
let (peer_id, inbound_request_id) = message_info.as_ref().unwrap();
receiver.send_response(*peer_id, *inbound_request_id, rpc_response.clone());
debug!("Sending message {}", messages_sent);
if messages_sent == messages_to_send + extra_messages_to_send {
@@ -648,7 +666,8 @@ fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() {
}
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
@@ -666,12 +685,12 @@ fn test_tcp_blocks_by_range_chunked_rpc_terminates_correctly() {
fn test_tcp_blocks_by_range_single_empty_rpc() {
// Set up the logging.
let log_level = "trace";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
rt.block_on(async {
// get sender/receiver
@@ -734,7 +753,8 @@ fn test_tcp_blocks_by_range_single_empty_rpc() {
_ => {} // Ignore other behaviour events
}
}
};
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
@@ -767,7 +787,8 @@ fn test_tcp_blocks_by_range_single_empty_rpc() {
_ => {} // Ignore other events
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
_ = receiver_future => {}
@@ -787,19 +808,20 @@ fn test_tcp_blocks_by_range_single_empty_rpc() {
fn test_tcp_blocks_by_root_chunked_rpc() {
// Set up the logging.
let log_level = "debug";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let messages_to_send = 6;
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
let current_fork_name = ForkName::Bellatrix;
let rt = Arc::new(Runtime::new().unwrap());
// get sender/receiver
rt.block_on(async {
let (mut sender, mut receiver) = common::build_node_pair(
Arc::downgrade(&rt),
ForkName::Bellatrix,
current_fork_name,
spec.clone(),
Protocol::Tcp,
false,
@@ -810,7 +832,7 @@ fn test_tcp_blocks_by_root_chunked_rpc() {
// BlocksByRoot Request
let rpc_request =
RequestType::BlocksByRoot(BlocksByRootRequest::V2(BlocksByRootRequestV2 {
block_roots: RuntimeVariableList::from_vec(
block_roots: RuntimeVariableList::new(
vec![
Hash256::zero(),
Hash256::zero(),
@@ -819,8 +841,9 @@ fn test_tcp_blocks_by_root_chunked_rpc() {
Hash256::zero(),
Hash256::zero(),
],
spec.max_request_blocks_upper_bound(),
),
spec.max_request_blocks(current_fork_name),
)
.unwrap(),
}));
// BlocksByRoot Response
@@ -877,7 +900,8 @@ fn test_tcp_blocks_by_root_chunked_rpc() {
_ => {} // Ignore other behaviour events
}
}
};
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
@@ -916,11 +940,320 @@ fn test_tcp_blocks_by_root_chunked_rpc() {
_ => {} // Ignore other events
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
_ = receiver_future => {}
_ = sleep(Duration::from_secs(30)) => {
_ = sleep(Duration::from_secs(300)) => {
panic!("Future timed out");
}
}
})
}
#[test]
#[allow(clippy::single_match)]
fn test_tcp_columns_by_root_chunked_rpc() {
// Set up the logging.
let log_level = "debug";
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let num_of_columns = E::number_of_columns();
let messages_to_send = 32 * num_of_columns;
let spec = Arc::new(spec_with_all_forks_enabled());
let current_fork_name = ForkName::Fulu;
let rt = Arc::new(Runtime::new().unwrap());
// get sender/receiver
rt.block_on(async {
let (mut sender, mut receiver) = common::build_node_pair(
Arc::downgrade(&rt),
current_fork_name,
spec.clone(),
Protocol::Tcp,
false,
None,
)
.await;
// DataColumnsByRootRequest Request
let max_request_blocks = spec.max_request_blocks(current_fork_name);
let req = DataColumnsByRootRequest::new(
vec![
DataColumnsByRootIdentifier {
block_root: Hash256::zero(),
columns: VariableList::new(
(0..E::number_of_columns() as u64).collect::<Vec<_>>()
)
.unwrap(),
};
max_request_blocks
],
max_request_blocks,
)
.unwrap();
let req_bytes = req.data_column_ids.as_ssz_bytes();
let req_decoded = DataColumnsByRootRequest {
data_column_ids: <RuntimeVariableList<DataColumnsByRootIdentifier<E>>>::from_ssz_bytes(
&req_bytes,
spec.max_request_blocks(current_fork_name),
)
.unwrap(),
};
assert_eq!(req, req_decoded);
let rpc_request = RequestType::DataColumnsByRoot(req);
// DataColumnsByRoot Response
let data_column = Arc::new(DataColumnSidecar {
index: 1,
signed_block_header: SignedBeaconBlockHeader {
message: BeaconBlockHeader {
slot: 320u64.into(),
proposer_index: 1,
parent_root: Hash256::zero(),
state_root: Hash256::zero(),
body_root: Hash256::zero(),
},
signature: Signature::empty(),
},
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
.try_into()
.unwrap(),
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
kzg_commitments_inclusion_proof: vec![
Hash256::zero();
E::kzg_commitments_inclusion_proof_depth()
]
.try_into()
.unwrap(),
});
let rpc_response = Response::DataColumnsByRoot(Some(data_column.clone()));
// keep count of the number of messages received
let mut messages_received = 0;
// build the sender future
let sender_future = async {
loop {
match sender.next_event().await {
NetworkEvent::PeerConnectedOutgoing(peer_id) => {
tracing::info!("Sending RPC");
tokio::time::sleep(Duration::from_secs(1)).await;
sender
.send_request(peer_id, AppRequestId::Router, rpc_request.clone())
.unwrap();
}
NetworkEvent::ResponseReceived {
peer_id: _,
app_request_id: AppRequestId::Router,
response,
} => match response {
Response::DataColumnsByRoot(Some(sidecar)) => {
assert_eq!(sidecar, data_column.clone());
messages_received += 1;
tracing::info!("Chunk received");
}
Response::DataColumnsByRoot(None) => {
// should be exactly messages_to_send
assert_eq!(messages_received, messages_to_send);
// end the test
return;
}
_ => {} // Ignore other RPC messages
},
_ => {} // Ignore other behaviour events
}
}
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
loop {
match receiver.next_event().await {
NetworkEvent::RequestReceived {
peer_id,
inbound_request_id,
request_type,
} => {
if request_type == rpc_request {
// send the response
tracing::info!("Receiver got request");
for _ in 0..messages_to_send {
receiver.send_response(
peer_id,
inbound_request_id,
rpc_response.clone(),
);
tracing::info!("Sending message");
}
// send the stream termination
receiver.send_response(
peer_id,
inbound_request_id,
Response::DataColumnsByRoot(None),
);
tracing::info!("Send stream term");
}
}
e => {
tracing::info!(?e, "Got event");
} // Ignore other events
}
}
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
_ = receiver_future => {}
_ = sleep(Duration::from_secs(300)) => {
panic!("Future timed out");
}
}
})
}
#[test]
#[allow(clippy::single_match)]
fn test_tcp_columns_by_range_chunked_rpc() {
// Set up the logging.
let log_level = "debug";
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let messages_to_send = 32;
let spec = Arc::new(spec_with_all_forks_enabled());
let current_fork_name = ForkName::Fulu;
let rt = Arc::new(Runtime::new().unwrap());
// get sender/receiver
rt.block_on(async {
let (mut sender, mut receiver) = common::build_node_pair(
Arc::downgrade(&rt),
current_fork_name,
spec.clone(),
Protocol::Tcp,
false,
None,
)
.await;
// DataColumnsByRange Request
let rpc_request = RequestType::DataColumnsByRange(DataColumnsByRangeRequest {
start_slot: 320,
count: 32,
columns: (0..E::number_of_columns() as u64).collect(),
});
// DataColumnsByRange Response
let data_column = Arc::new(DataColumnSidecar {
index: 1,
signed_block_header: SignedBeaconBlockHeader {
message: BeaconBlockHeader {
slot: 320u64.into(),
proposer_index: 1,
parent_root: Hash256::zero(),
state_root: Hash256::zero(),
body_root: Hash256::zero(),
},
signature: Signature::empty(),
},
column: vec![vec![0; E::bytes_per_cell()].try_into().unwrap()]
.try_into()
.unwrap(),
kzg_commitments: vec![KzgCommitment::empty_for_testing()].try_into().unwrap(),
kzg_proofs: vec![KzgProof::empty()].try_into().unwrap(),
kzg_commitments_inclusion_proof: vec![
Hash256::zero();
E::kzg_commitments_inclusion_proof_depth()
]
.try_into()
.unwrap(),
});
let rpc_response = Response::DataColumnsByRange(Some(data_column.clone()));
// keep count of the number of messages received
let mut messages_received = 0;
// build the sender future
let sender_future = async {
loop {
match sender.next_event().await {
NetworkEvent::PeerConnectedOutgoing(peer_id) => {
tracing::info!("Sending RPC");
sender
.send_request(peer_id, AppRequestId::Router, rpc_request.clone())
.unwrap();
}
NetworkEvent::ResponseReceived {
peer_id: _,
app_request_id: AppRequestId::Router,
response,
} => match response {
Response::DataColumnsByRange(Some(sidecar)) => {
assert_eq!(sidecar, data_column.clone());
messages_received += 1;
tracing::info!("Chunk received");
}
Response::DataColumnsByRange(None) => {
// should be exactly messages_to_send
assert_eq!(messages_received, messages_to_send);
// end the test
return;
}
_ => {} // Ignore other RPC messages
},
_ => {} // Ignore other behaviour events
}
}
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
loop {
match receiver.next_event().await {
NetworkEvent::RequestReceived {
peer_id,
inbound_request_id,
request_type,
} => {
if request_type == rpc_request {
// send the response
tracing::info!("Receiver got request");
for _ in 0..messages_to_send {
receiver.send_response(
peer_id,
inbound_request_id,
rpc_response.clone(),
);
tracing::info!("Sending message");
}
// send the stream termination
receiver.send_response(
peer_id,
inbound_request_id,
Response::DataColumnsByRange(None),
);
tracing::info!("Send stream term");
}
}
_ => {} // Ignore other events
}
}
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
_ = receiver_future => {}
_ = sleep(Duration::from_secs(300)) => {
panic!("Future timed out");
}
}
@@ -932,20 +1265,21 @@ fn test_tcp_blocks_by_root_chunked_rpc() {
fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
// Set up the logging.
let log_level = "debug";
let enable_logging = false;
build_tracing_subscriber(log_level, enable_logging);
let enable_logging = true;
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let messages_to_send: u64 = 10;
let extra_messages_to_send: u64 = 10;
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
let current_fork = ForkName::Base;
let rt = Arc::new(Runtime::new().unwrap());
// get sender/receiver
rt.block_on(async {
let (mut sender, mut receiver) = common::build_node_pair(
Arc::downgrade(&rt),
ForkName::Base,
current_fork,
spec.clone(),
Protocol::Tcp,
false,
@@ -956,7 +1290,7 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
// BlocksByRoot Request
let rpc_request =
RequestType::BlocksByRoot(BlocksByRootRequest::V2(BlocksByRootRequestV2 {
block_roots: RuntimeVariableList::from_vec(
block_roots: RuntimeVariableList::new(
vec![
Hash256::zero(),
Hash256::zero(),
@@ -969,8 +1303,9 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
Hash256::zero(),
Hash256::zero(),
],
spec.max_request_blocks_upper_bound(),
),
spec.max_request_blocks(current_fork),
)
.unwrap(),
}));
// BlocksByRoot Response
@@ -1015,7 +1350,8 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
_ => {} // Ignore other behaviour events
}
}
};
}
.instrument(info_span!("Sender"));
// determine messages to send (PeerId, RequestId). If some, indicates we still need to send
// messages
@@ -1051,9 +1387,8 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
}
// if we need to send messages send them here. This will happen after a delay
if message_info.is_some() {
if let Some((peer_id, inbound_request_id)) = &message_info {
messages_sent += 1;
let (peer_id, inbound_request_id) = message_info.as_ref().unwrap();
receiver.send_response(*peer_id, *inbound_request_id, rpc_response.clone());
debug!("Sending message {}", messages_sent);
if messages_sent == messages_to_send + extra_messages_to_send {
@@ -1062,7 +1397,8 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
}
}
}
};
}
.instrument(info_span!("Receiver"));
tokio::select! {
_ = sender_future => {}
@@ -1078,11 +1414,11 @@ fn test_tcp_blocks_by_root_chunked_rpc_terminates_correctly() {
/// Goodbye message.
fn goodbye_test(log_level: &str, enable_logging: bool, protocol: Protocol) {
// Set up the logging.
build_tracing_subscriber(log_level, enable_logging);
let _subscriber = build_tracing_subscriber(log_level, enable_logging);
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
// get sender/receiver
rt.block_on(async {
@@ -1115,7 +1451,8 @@ fn goodbye_test(log_level: &str, enable_logging: bool, protocol: Protocol) {
_ => {} // Ignore other RPC messages
}
}
};
}
.instrument(info_span!("Sender"));
// build the receiver future
let receiver_future = async {
@@ -1125,7 +1462,8 @@ fn goodbye_test(log_level: &str, enable_logging: bool, protocol: Protocol) {
return;
}
}
};
}
.instrument(info_span!("Receiver"));
let total_future = futures::future::join(sender_future, receiver_future);
@@ -1143,7 +1481,7 @@ fn goodbye_test(log_level: &str, enable_logging: bool, protocol: Protocol) {
#[allow(clippy::single_match)]
fn tcp_test_goodbye_rpc() {
let log_level = "debug";
let enabled_logging = false;
let enabled_logging = true;
goodbye_test(log_level, enabled_logging, Protocol::Tcp);
}
@@ -1152,15 +1490,17 @@ fn tcp_test_goodbye_rpc() {
#[allow(clippy::single_match)]
fn quic_test_goodbye_rpc() {
let log_level = "debug";
let enabled_logging = false;
let enabled_logging = true;
goodbye_test(log_level, enabled_logging, Protocol::Quic);
}
// Test that the receiver delays the responses during response rate-limiting.
#[test]
fn test_delayed_rpc_response() {
// Set up the logging.
let _subscriber = build_tracing_subscriber("debug", true);
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
// Allow 1 token to be use used every 3 seconds.
const QUOTA_SEC: u64 = 3;
@@ -1179,22 +1519,24 @@ fn test_delayed_rpc_response() {
.await;
// Dummy STATUS RPC message
let rpc_request = RequestType::Status(StatusMessage {
let rpc_request = RequestType::Status(StatusMessage::V2(StatusMessageV2 {
fork_digest: [0; 4],
finalized_root: Hash256::from_low_u64_be(0),
finalized_epoch: Epoch::new(1),
head_root: Hash256::from_low_u64_be(0),
head_slot: Slot::new(1),
});
earliest_available_slot: Slot::new(0),
}));
// Dummy STATUS RPC message
let rpc_response = Response::Status(StatusMessage {
let rpc_response = Response::Status(StatusMessage::V2(StatusMessageV2 {
fork_digest: [0; 4],
finalized_root: Hash256::from_low_u64_be(0),
finalized_epoch: Epoch::new(1),
head_root: Hash256::from_low_u64_be(0),
head_slot: Slot::new(1),
});
earliest_available_slot: Slot::new(0),
}));
// build the sender future
let sender_future = async {
@@ -1214,7 +1556,7 @@ fn test_delayed_rpc_response() {
app_request_id: _,
response,
} => {
debug!(%request_id, "Sender received");
debug!(%request_id, elapsed = ?request_sent_at.elapsed(), "Sender received response");
assert_eq!(response, rpc_response);
match request_id {
@@ -1226,10 +1568,12 @@ fn test_delayed_rpc_response() {
// The second and subsequent responses are delayed due to the response rate-limiter on the receiver side.
// Adding a slight margin to the elapsed time check to account for potential timing issues caused by system
// scheduling or execution delays during testing.
// https://github.com/sigp/lighthouse/issues/7466
let margin = 500;
assert!(
request_sent_at.elapsed()
> (Duration::from_secs(QUOTA_SEC)
- Duration::from_millis(100))
- Duration::from_millis(margin))
);
if request_id == 5 {
// End the test
@@ -1289,8 +1633,10 @@ fn test_delayed_rpc_response() {
// once, thanks to the self-limiter on the sender side.
#[test]
fn test_active_requests() {
// Set up the logging.
let _subscriber = build_tracing_subscriber("debug", true);
let rt = Arc::new(Runtime::new().unwrap());
let spec = Arc::new(E::default_spec());
let spec = Arc::new(spec_with_all_forks_enabled());
rt.block_on(async {
// Get sender/receiver.
@@ -1305,22 +1651,24 @@ fn test_active_requests() {
.await;
// Dummy STATUS RPC request.
let rpc_request = RequestType::Status(StatusMessage {
let rpc_request = RequestType::Status(StatusMessage::V2(StatusMessageV2 {
fork_digest: [0; 4],
finalized_root: Hash256::from_low_u64_be(0),
finalized_epoch: Epoch::new(1),
head_root: Hash256::from_low_u64_be(0),
head_slot: Slot::new(1),
});
earliest_available_slot: Slot::new(0),
}));
// Dummy STATUS RPC response.
let rpc_response = Response::Status(StatusMessage {
let rpc_response = Response::Status(StatusMessage::V2(StatusMessageV2 {
fork_digest: [0; 4],
finalized_root: Hash256::zero(),
finalized_epoch: Epoch::new(1),
head_root: Hash256::zero(),
head_slot: Slot::new(1),
});
earliest_available_slot: Slot::new(0),
}));
// Number of requests.
const REQUESTS: u8 = 10;