mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-06 10:11:44 +00:00
Increase network limits (#2796)
Fix max packet sizes Fix max_payload_size function Add merge block test Fix max size calculation; fix up test Clear comments Add a payload_size_function Use safe arith for payload calculation Return an error if block too big in block production Separate test to check if block is over limit
This commit is contained in:
@@ -1,21 +1,52 @@
|
||||
#![cfg(test)]
|
||||
use lighthouse_network::rpc::methods::*;
|
||||
use lighthouse_network::{BehaviourEvent, Libp2pEvent, ReportSource, Request, Response};
|
||||
use lighthouse_network::{
|
||||
rpc::MAX_RPC_SIZE, BehaviourEvent, Libp2pEvent, ReportSource, Request, Response,
|
||||
};
|
||||
use slog::{debug, warn, Level};
|
||||
use ssz::Encode;
|
||||
use ssz_types::VariableList;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio::time::sleep;
|
||||
use types::{
|
||||
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, Epoch, EthSpec, Hash256, MinimalEthSpec,
|
||||
Signature, SignedBeaconBlock, Slot,
|
||||
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockMerge, Epoch, EthSpec, Hash256,
|
||||
MinimalEthSpec, Signature, SignedBeaconBlock, Slot,
|
||||
};
|
||||
|
||||
mod common;
|
||||
|
||||
type E = MinimalEthSpec;
|
||||
|
||||
/// Merge block with length < MAX_RPC_SIZE.
|
||||
fn merge_block_small() -> BeaconBlock<E> {
|
||||
let mut block = BeaconBlockMerge::empty(&E::default_spec());
|
||||
let tx = VariableList::from(vec![0; 1024]);
|
||||
let txs = VariableList::from(std::iter::repeat(tx).take(100).collect::<Vec<_>>());
|
||||
|
||||
block.body.execution_payload.transactions = txs;
|
||||
|
||||
let block = BeaconBlock::Merge(block);
|
||||
assert!(block.ssz_bytes_len() <= MAX_RPC_SIZE);
|
||||
block
|
||||
}
|
||||
|
||||
/// Merge block with length > MAX_RPC_SIZE.
|
||||
/// The max limit for a merge block is in the order of ~16GiB which wouldn't fit in memory.
|
||||
/// Hence, we generate a merge block just greater than `MAX_RPC_SIZE` to test rejection on the rpc layer.
|
||||
fn merge_block_large() -> BeaconBlock<E> {
|
||||
let mut block = BeaconBlockMerge::empty(&E::default_spec());
|
||||
let tx = VariableList::from(vec![0; 1024]);
|
||||
let txs = VariableList::from(std::iter::repeat(tx).take(100000).collect::<Vec<_>>());
|
||||
|
||||
block.body.execution_payload.transactions = txs;
|
||||
|
||||
let block = BeaconBlock::Merge(block);
|
||||
assert!(block.ssz_bytes_len() > MAX_RPC_SIZE);
|
||||
block
|
||||
}
|
||||
|
||||
// Tests the STATUS RPC message
|
||||
#[test]
|
||||
#[allow(clippy::single_match)]
|
||||
@@ -118,10 +149,10 @@ fn test_status_rpc() {
|
||||
#[allow(clippy::single_match)]
|
||||
fn test_blocks_by_range_chunked_rpc() {
|
||||
// set up the logging. The level and enabled logging or not
|
||||
let log_level = Level::Trace;
|
||||
let log_level = Level::Debug;
|
||||
let enable_logging = false;
|
||||
|
||||
let messages_to_send = 10;
|
||||
let messages_to_send = 6;
|
||||
|
||||
let log = common::build_log(log_level, enable_logging);
|
||||
|
||||
@@ -149,8 +180,13 @@ fn test_blocks_by_range_chunked_rpc() {
|
||||
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
|
||||
let rpc_response_altair = Response::BlocksByRange(Some(Box::new(signed_full_block)));
|
||||
|
||||
let full_block = merge_block_small();
|
||||
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
|
||||
let rpc_response_merge_small = Response::BlocksByRange(Some(Box::new(signed_full_block)));
|
||||
|
||||
// keep count of the number of messages received
|
||||
let mut messages_received = 0;
|
||||
let request_id = RequestId::Sync(messages_to_send as usize);
|
||||
// build the sender future
|
||||
let sender_future = async {
|
||||
loop {
|
||||
@@ -160,28 +196,30 @@ fn test_blocks_by_range_chunked_rpc() {
|
||||
debug!(log, "Sending RPC");
|
||||
sender.swarm.behaviour_mut().send_request(
|
||||
peer_id,
|
||||
RequestId::Sync(10),
|
||||
request_id,
|
||||
rpc_request.clone(),
|
||||
);
|
||||
}
|
||||
Libp2pEvent::Behaviour(BehaviourEvent::ResponseReceived {
|
||||
peer_id: _,
|
||||
id: RequestId::Sync(10),
|
||||
id: _,
|
||||
response,
|
||||
}) => {
|
||||
warn!(log, "Sender received a response");
|
||||
match response {
|
||||
Response::BlocksByRange(Some(_)) => {
|
||||
if messages_received < 5 {
|
||||
if messages_received < 2 {
|
||||
assert_eq!(response, rpc_response_base.clone());
|
||||
} else {
|
||||
} else if messages_received < 4 {
|
||||
assert_eq!(response, rpc_response_altair.clone());
|
||||
} else {
|
||||
assert_eq!(response, rpc_response_merge_small.clone());
|
||||
}
|
||||
messages_received += 1;
|
||||
warn!(log, "Chunk received");
|
||||
}
|
||||
Response::BlocksByRange(None) => {
|
||||
// should be exactly 10 messages before terminating
|
||||
// should be exactly `messages_to_send` messages before terminating
|
||||
assert_eq!(messages_received, messages_to_send);
|
||||
// end the test
|
||||
return;
|
||||
@@ -207,12 +245,14 @@ fn test_blocks_by_range_chunked_rpc() {
|
||||
// send the response
|
||||
warn!(log, "Receiver got request");
|
||||
for i in 0..messages_to_send {
|
||||
// Send first half of responses as base blocks and
|
||||
// second half as altair blocks.
|
||||
let rpc_response = if i < 5 {
|
||||
// Send first third of responses as base blocks,
|
||||
// second as altair and third as merge.
|
||||
let rpc_response = if i < 2 {
|
||||
rpc_response_base.clone()
|
||||
} else {
|
||||
} else if i < 4 {
|
||||
rpc_response_altair.clone()
|
||||
} else {
|
||||
rpc_response_merge_small.clone()
|
||||
};
|
||||
receiver.swarm.behaviour_mut().send_successful_response(
|
||||
peer_id,
|
||||
@@ -236,8 +276,105 @@ fn test_blocks_by_range_chunked_rpc() {
|
||||
tokio::select! {
|
||||
_ = sender_future => {}
|
||||
_ = receiver_future => {}
|
||||
_ = sleep(Duration::from_secs(10)) => {
|
||||
panic!("Future timed out");
|
||||
_ = sleep(Duration::from_secs(30)) => {
|
||||
panic!("Future timed out");
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Tests rejection of blocks over `MAX_RPC_SIZE`.
|
||||
#[test]
|
||||
#[allow(clippy::single_match)]
|
||||
fn test_blocks_by_range_over_limit() {
|
||||
// set up the logging. The level and enabled logging or not
|
||||
let log_level = Level::Debug;
|
||||
let enable_logging = false;
|
||||
|
||||
let messages_to_send = 5;
|
||||
|
||||
let log = common::build_log(log_level, enable_logging);
|
||||
|
||||
let rt = Arc::new(Runtime::new().unwrap());
|
||||
|
||||
rt.block_on(async {
|
||||
// get sender/receiver
|
||||
let (mut sender, mut receiver) = common::build_node_pair(Arc::downgrade(&rt), &log).await;
|
||||
|
||||
// BlocksByRange Request
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest {
|
||||
start_slot: 0,
|
||||
count: messages_to_send,
|
||||
step: 0,
|
||||
});
|
||||
|
||||
// BlocksByRange Response
|
||||
let full_block = merge_block_large();
|
||||
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
|
||||
let rpc_response_merge_large = Response::BlocksByRange(Some(Box::new(signed_full_block)));
|
||||
|
||||
let request_id = RequestId::Sync(messages_to_send as usize);
|
||||
// build the sender future
|
||||
let sender_future = async {
|
||||
loop {
|
||||
match sender.next_event().await {
|
||||
Libp2pEvent::Behaviour(BehaviourEvent::PeerConnectedOutgoing(peer_id)) => {
|
||||
// Send a STATUS message
|
||||
debug!(log, "Sending RPC");
|
||||
sender.swarm.behaviour_mut().send_request(
|
||||
peer_id,
|
||||
request_id,
|
||||
rpc_request.clone(),
|
||||
);
|
||||
}
|
||||
// The request will fail because the sender will refuse to send anything > MAX_RPC_SIZE
|
||||
Libp2pEvent::Behaviour(BehaviourEvent::RPCFailed { id, .. }) => {
|
||||
assert_eq!(id, request_id);
|
||||
return;
|
||||
}
|
||||
_ => {} // Ignore other behaviour events
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// build the receiver future
|
||||
let receiver_future = async {
|
||||
loop {
|
||||
match receiver.next_event().await {
|
||||
Libp2pEvent::Behaviour(BehaviourEvent::RequestReceived {
|
||||
peer_id,
|
||||
id,
|
||||
request,
|
||||
}) => {
|
||||
if request == rpc_request {
|
||||
// send the response
|
||||
warn!(log, "Receiver got request");
|
||||
for _ in 0..messages_to_send {
|
||||
let rpc_response = rpc_response_merge_large.clone();
|
||||
receiver.swarm.behaviour_mut().send_successful_response(
|
||||
peer_id,
|
||||
id,
|
||||
rpc_response.clone(),
|
||||
);
|
||||
}
|
||||
// send the stream termination
|
||||
receiver.swarm.behaviour_mut().send_successful_response(
|
||||
peer_id,
|
||||
id,
|
||||
Response::BlocksByRange(None),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {} // Ignore other events
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tokio::select! {
|
||||
_ = sender_future => {}
|
||||
_ = receiver_future => {}
|
||||
_ = sleep(Duration::from_secs(30)) => {
|
||||
panic!("Future timed out");
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -276,6 +413,7 @@ fn test_blocks_by_range_chunked_rpc_terminates_correctly() {
|
||||
|
||||
// keep count of the number of messages received
|
||||
let mut messages_received: u64 = 0;
|
||||
let request_id = RequestId::Sync(messages_to_send as usize);
|
||||
// build the sender future
|
||||
let sender_future = async {
|
||||
loop {
|
||||
@@ -285,13 +423,13 @@ fn test_blocks_by_range_chunked_rpc_terminates_correctly() {
|
||||
debug!(log, "Sending RPC");
|
||||
sender.swarm.behaviour_mut().send_request(
|
||||
peer_id,
|
||||
RequestId::Sync(10),
|
||||
request_id,
|
||||
rpc_request.clone(),
|
||||
);
|
||||
}
|
||||
Libp2pEvent::Behaviour(BehaviourEvent::ResponseReceived {
|
||||
peer_id: _,
|
||||
id: RequestId::Sync(10),
|
||||
id: _,
|
||||
response,
|
||||
}) =>
|
||||
// Should receive the RPC response
|
||||
@@ -497,7 +635,7 @@ fn test_blocks_by_root_chunked_rpc() {
|
||||
let log_level = Level::Debug;
|
||||
let enable_logging = false;
|
||||
|
||||
let messages_to_send = 10;
|
||||
let messages_to_send = 6;
|
||||
|
||||
let log = common::build_log(log_level, enable_logging);
|
||||
let spec = E::default_spec();
|
||||
@@ -516,10 +654,6 @@ fn test_blocks_by_root_chunked_rpc() {
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
]),
|
||||
});
|
||||
|
||||
@@ -532,6 +666,10 @@ fn test_blocks_by_root_chunked_rpc() {
|
||||
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
|
||||
let rpc_response_altair = Response::BlocksByRoot(Some(Box::new(signed_full_block)));
|
||||
|
||||
let full_block = merge_block_small();
|
||||
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
|
||||
let rpc_response_merge_small = Response::BlocksByRoot(Some(Box::new(signed_full_block)));
|
||||
|
||||
// keep count of the number of messages received
|
||||
let mut messages_received = 0;
|
||||
// build the sender future
|
||||
@@ -543,20 +681,22 @@ fn test_blocks_by_root_chunked_rpc() {
|
||||
debug!(log, "Sending RPC");
|
||||
sender.swarm.behaviour_mut().send_request(
|
||||
peer_id,
|
||||
RequestId::Sync(10),
|
||||
RequestId::Sync(6),
|
||||
rpc_request.clone(),
|
||||
);
|
||||
}
|
||||
Libp2pEvent::Behaviour(BehaviourEvent::ResponseReceived {
|
||||
peer_id: _,
|
||||
id: RequestId::Sync(10),
|
||||
id: RequestId::Sync(6),
|
||||
response,
|
||||
}) => match response {
|
||||
Response::BlocksByRoot(Some(_)) => {
|
||||
if messages_received < 5 {
|
||||
if messages_received < 2 {
|
||||
assert_eq!(response, rpc_response_base.clone());
|
||||
} else {
|
||||
} else if messages_received < 4 {
|
||||
assert_eq!(response, rpc_response_altair.clone());
|
||||
} else {
|
||||
assert_eq!(response, rpc_response_merge_small.clone());
|
||||
}
|
||||
messages_received += 1;
|
||||
debug!(log, "Chunk received");
|
||||
@@ -588,12 +728,13 @@ fn test_blocks_by_root_chunked_rpc() {
|
||||
debug!(log, "Receiver got request");
|
||||
|
||||
for i in 0..messages_to_send {
|
||||
// Send first half of responses as base blocks and
|
||||
// second half as altair blocks.
|
||||
let rpc_response = if i < 5 {
|
||||
// Send equal base, altair and merge blocks
|
||||
let rpc_response = if i < 2 {
|
||||
rpc_response_base.clone()
|
||||
} else {
|
||||
} else if i < 4 {
|
||||
rpc_response_altair.clone()
|
||||
} else {
|
||||
rpc_response_merge_small.clone()
|
||||
};
|
||||
receiver.swarm.behaviour_mut().send_successful_response(
|
||||
peer_id,
|
||||
@@ -619,7 +760,7 @@ fn test_blocks_by_root_chunked_rpc() {
|
||||
_ = sender_future => {}
|
||||
_ = receiver_future => {}
|
||||
_ = sleep(Duration::from_secs(30)) => {
|
||||
panic!("Future timed out");
|
||||
panic!("Future timed out");
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user