Merge branch 'release-v7.0.0' into unstable

This commit is contained in:
Mac L
2025-04-11 20:21:40 +10:00
40 changed files with 825 additions and 432 deletions

View File

@@ -14,7 +14,7 @@ use std::num::NonZeroU16;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;
use types::{ForkContext, ForkName};
use types::ForkContext;
pub const DEFAULT_IPV4_ADDRESS: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
pub const DEFAULT_TCP_PORT: u16 = 9000u16;
@@ -22,18 +22,9 @@ pub const DEFAULT_DISC_PORT: u16 = 9000u16;
pub const DEFAULT_QUIC_PORT: u16 = 9001u16;
pub const DEFAULT_IDONTWANT_MESSAGE_SIZE_THRESHOLD: usize = 1000usize;
/// The maximum size of gossip messages.
pub fn gossip_max_size(is_merge_enabled: bool, gossip_max_size: usize) -> usize {
if is_merge_enabled {
gossip_max_size
} else {
gossip_max_size / 10
}
}
pub struct GossipsubConfigParams {
pub message_domain_valid_snappy: [u8; 4],
pub gossip_max_size: usize,
pub gossipsub_max_transmit_size: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -480,7 +471,6 @@ pub fn gossipsub_config(
}
}
let message_domain_valid_snappy = gossipsub_config_params.message_domain_valid_snappy;
let is_bellatrix_enabled = fork_context.fork_exists(ForkName::Bellatrix);
let gossip_message_id = move |message: &gossipsub::Message| {
gossipsub::MessageId::from(
&Sha256::digest(
@@ -499,10 +489,7 @@ pub fn gossipsub_config(
let duplicate_cache_time = Duration::from_secs(slots_per_epoch * seconds_per_slot * 2);
gossipsub::ConfigBuilder::default()
.max_transmit_size(gossip_max_size(
is_bellatrix_enabled,
gossipsub_config_params.gossip_max_size,
))
.max_transmit_size(gossipsub_config_params.gossipsub_max_transmit_size)
.heartbeat_interval(load.heartbeat_interval)
.mesh_n(load.mesh_n)
.mesh_n_low(load.mesh_n_low)

View File

@@ -12,7 +12,6 @@ pub mod peer_manager;
pub mod rpc;
pub mod types;
pub use config::gossip_max_size;
use libp2p::swarm::DialError;
pub use listen_addr::*;

View File

@@ -1002,10 +1002,7 @@ mod tests {
}
/// Bellatrix block with length < max_rpc_size.
fn bellatrix_block_small(
fork_context: &ForkContext,
spec: &ChainSpec,
) -> SignedBeaconBlock<Spec> {
fn bellatrix_block_small(spec: &ChainSpec) -> SignedBeaconBlock<Spec> {
let mut block: BeaconBlockBellatrix<_, FullPayload<Spec>> =
BeaconBlockBellatrix::empty(&Spec::default_spec());
@@ -1015,17 +1012,14 @@ mod tests {
block.body.execution_payload.execution_payload.transactions = txs;
let block = BeaconBlock::Bellatrix(block);
assert!(block.ssz_bytes_len() <= max_rpc_size(fork_context, spec.max_chunk_size as usize));
assert!(block.ssz_bytes_len() <= spec.max_payload_size as usize);
SignedBeaconBlock::from_block(block, Signature::empty())
}
/// Bellatrix block with length > MAX_RPC_SIZE.
/// The max limit for a Bellatrix block is in the order of ~16GiB which wouldn't fit in memory.
/// Hence, we generate a Bellatrix block just greater than `MAX_RPC_SIZE` to test rejection on the rpc layer.
fn bellatrix_block_large(
fork_context: &ForkContext,
spec: &ChainSpec,
) -> SignedBeaconBlock<Spec> {
fn bellatrix_block_large(spec: &ChainSpec) -> SignedBeaconBlock<Spec> {
let mut block: BeaconBlockBellatrix<_, FullPayload<Spec>> =
BeaconBlockBellatrix::empty(&Spec::default_spec());
@@ -1035,7 +1029,7 @@ mod tests {
block.body.execution_payload.execution_payload.transactions = txs;
let block = BeaconBlock::Bellatrix(block);
assert!(block.ssz_bytes_len() > max_rpc_size(fork_context, spec.max_chunk_size as usize));
assert!(block.ssz_bytes_len() > spec.max_payload_size as usize);
SignedBeaconBlock::from_block(block, Signature::empty())
}
@@ -1143,7 +1137,7 @@ mod tests {
) -> Result<BytesMut, RPCError> {
let snappy_protocol_id = ProtocolId::new(protocol, Encoding::SSZSnappy);
let fork_context = Arc::new(fork_context(fork_name));
let max_packet_size = max_rpc_size(&fork_context, spec.max_chunk_size as usize);
let max_packet_size = spec.max_payload_size as usize;
let mut buf = BytesMut::new();
let mut snappy_inbound_codec =
@@ -1190,7 +1184,7 @@ mod tests {
) -> Result<Option<RpcSuccessResponse<Spec>>, RPCError> {
let snappy_protocol_id = ProtocolId::new(protocol, Encoding::SSZSnappy);
let fork_context = Arc::new(fork_context(fork_name));
let max_packet_size = max_rpc_size(&fork_context, spec.max_chunk_size as usize);
let max_packet_size = spec.max_payload_size as usize;
let mut snappy_outbound_codec =
SSZSnappyOutboundCodec::<Spec>::new(snappy_protocol_id, max_packet_size, fork_context);
// decode message just as snappy message
@@ -1211,7 +1205,7 @@ mod tests {
/// Verifies that requests we send are encoded in a way that we would correctly decode too.
fn encode_then_decode_request(req: RequestType<Spec>, fork_name: ForkName, spec: &ChainSpec) {
let fork_context = Arc::new(fork_context(fork_name));
let max_packet_size = max_rpc_size(&fork_context, spec.max_chunk_size as usize);
let max_packet_size = spec.max_payload_size as usize;
let protocol = ProtocolId::new(req.versioned_protocol(), Encoding::SSZSnappy);
// Encode a request we send
let mut buf = BytesMut::new();
@@ -1588,10 +1582,8 @@ mod tests {
))))
);
let bellatrix_block_small =
bellatrix_block_small(&fork_context(ForkName::Bellatrix), &chain_spec);
let bellatrix_block_large =
bellatrix_block_large(&fork_context(ForkName::Bellatrix), &chain_spec);
let bellatrix_block_small = bellatrix_block_small(&chain_spec);
let bellatrix_block_large = bellatrix_block_large(&chain_spec);
assert_eq!(
encode_then_decode_response(
@@ -2091,7 +2083,7 @@ mod tests {
// Insert length-prefix
uvi_codec
.encode(chain_spec.max_chunk_size as usize + 1, &mut dst)
.encode(chain_spec.max_payload_size as usize + 1, &mut dst)
.unwrap();
// Insert snappy stream identifier
@@ -2129,7 +2121,7 @@ mod tests {
let mut snappy_outbound_codec = SSZSnappyOutboundCodec::<Spec>::new(
snappy_protocol_id,
max_rpc_size(&fork_context, chain_spec.max_chunk_size as usize),
chain_spec.max_payload_size as usize,
fork_context,
);
@@ -2165,7 +2157,7 @@ mod tests {
let mut snappy_outbound_codec = SSZSnappyOutboundCodec::<Spec>::new(
snappy_protocol_id,
max_rpc_size(&fork_context, chain_spec.max_chunk_size as usize),
chain_spec.max_payload_size as usize,
fork_context,
);
@@ -2194,7 +2186,7 @@ mod tests {
let chain_spec = Spec::default_spec();
let max_rpc_size = max_rpc_size(&fork_context, chain_spec.max_chunk_size as usize);
let max_rpc_size = chain_spec.max_payload_size as usize;
let limit = protocol_id.rpc_response_limits::<Spec>(&fork_context);
let mut max = encode_len(limit.max + 1);
let mut codec = SSZSnappyOutboundCodec::<Spec>::new(

View File

@@ -33,7 +33,7 @@ pub use methods::{
BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, LightClientBootstrapRequest,
ResponseTermination, RpcErrorResponse, StatusMessage,
};
pub use protocol::{max_rpc_size, Protocol, RPCError};
pub use protocol::{Protocol, RPCError};
use self::config::{InboundRateLimiterConfig, OutboundRateLimiterConfig};
use self::protocol::RPCProtocol;
@@ -136,7 +136,7 @@ pub struct RPCMessage<Id, E: EthSpec> {
type BehaviourAction<Id, E> = ToSwarm<RPCMessage<Id, E>, RPCSend<Id, E>>;
pub struct NetworkParams {
pub max_chunk_size: usize,
pub max_payload_size: usize,
pub ttfb_timeout: Duration,
pub resp_timeout: Duration,
}
@@ -306,7 +306,7 @@ where
let protocol = SubstreamProtocol::new(
RPCProtocol {
fork_context: self.fork_context.clone(),
max_rpc_size: max_rpc_size(&self.fork_context, self.network_params.max_chunk_size),
max_rpc_size: self.fork_context.spec.max_payload_size as usize,
enable_light_client_server: self.enable_light_client_server,
phantom: PhantomData,
ttfb_timeout: self.network_params.ttfb_timeout,
@@ -336,7 +336,7 @@ where
let protocol = SubstreamProtocol::new(
RPCProtocol {
fork_context: self.fork_context.clone(),
max_rpc_size: max_rpc_size(&self.fork_context, self.network_params.max_chunk_size),
max_rpc_size: self.fork_context.spec.max_payload_size as usize,
enable_light_client_server: self.enable_light_client_server,
phantom: PhantomData,
ttfb_timeout: self.network_params.ttfb_timeout,

View File

@@ -57,7 +57,7 @@ pub static SIGNED_BEACON_BLOCK_ALTAIR_MAX: LazyLock<usize> = LazyLock::new(|| {
/// The `BeaconBlockBellatrix` block has an `ExecutionPayload` field which has a max size ~16 GiB for future proofing.
/// We calculate the value from its fields instead of constructing the block and checking the length.
/// Note: This is only the theoretical upper bound. We further bound the max size we receive over the network
/// with `max_chunk_size`.
/// with `max_payload_size`.
pub static SIGNED_BEACON_BLOCK_BELLATRIX_MAX: LazyLock<usize> =
LazyLock::new(|| // Size of a full altair block
*SIGNED_BEACON_BLOCK_ALTAIR_MAX
@@ -122,15 +122,6 @@ const PROTOCOL_PREFIX: &str = "/eth2/beacon_chain/req";
/// established before the stream is terminated.
const REQUEST_TIMEOUT: u64 = 15;
/// Returns the maximum bytes that can be sent across the RPC.
pub fn max_rpc_size(fork_context: &ForkContext, max_chunk_size: usize) -> usize {
if fork_context.current_fork().bellatrix_enabled() {
max_chunk_size
} else {
max_chunk_size / 10
}
}
/// Returns the rpc limits for beacon_block_by_range and beacon_block_by_root responses.
///
/// Note: This function should take care to return the min/max limits accounting for all

View File

@@ -223,7 +223,7 @@ impl<E: EthSpec> Network<E> {
let gossipsub_config_params = GossipsubConfigParams {
message_domain_valid_snappy: ctx.chain_spec.message_domain_valid_snappy,
gossip_max_size: ctx.chain_spec.gossip_max_size as usize,
gossipsub_max_transmit_size: ctx.chain_spec.max_message_size(),
};
let gs_config = gossipsub_config(
config.network_load,
@@ -334,7 +334,9 @@ impl<E: EthSpec> Network<E> {
)
});
let snappy_transform = SnappyTransform::new(gs_config.max_transmit_size());
let spec = &ctx.chain_spec;
let snappy_transform =
SnappyTransform::new(spec.max_payload_size as usize, spec.max_compressed_len());
let mut gossipsub = Gossipsub::new_with_subscription_filter_and_transform(
MessageAuthenticity::Anonymous,
gs_config.clone(),
@@ -365,7 +367,7 @@ impl<E: EthSpec> Network<E> {
};
let network_params = NetworkParams {
max_chunk_size: ctx.chain_spec.max_chunk_size as usize,
max_payload_size: ctx.chain_spec.max_payload_size as usize,
ttfb_timeout: ctx.chain_spec.ttfb_timeout(),
resp_timeout: ctx.chain_spec.resp_timeout(),
};

View File

@@ -52,13 +52,16 @@ pub enum PubsubMessage<E: EthSpec> {
// Implements the `DataTransform` trait of gossipsub to employ snappy compression
pub struct SnappyTransform {
/// Sets the maximum size we allow gossipsub messages to decompress to.
max_size_per_message: usize,
max_uncompressed_len: usize,
/// Sets the maximum size we allow for compressed gossipsub message data.
max_compressed_len: usize,
}
impl SnappyTransform {
pub fn new(max_size_per_message: usize) -> Self {
pub fn new(max_uncompressed_len: usize, max_compressed_len: usize) -> Self {
SnappyTransform {
max_size_per_message,
max_uncompressed_len,
max_compressed_len,
}
}
}
@@ -69,12 +72,19 @@ impl gossipsub::DataTransform for SnappyTransform {
&self,
raw_message: gossipsub::RawMessage,
) -> Result<gossipsub::Message, std::io::Error> {
// check the length of the raw bytes
let len = decompress_len(&raw_message.data)?;
if len > self.max_size_per_message {
// first check the size of the compressed payload
if raw_message.data.len() > self.max_compressed_len {
return Err(Error::new(
ErrorKind::InvalidData,
"ssz_snappy decoded data > GOSSIP_MAX_SIZE",
"ssz_snappy encoded data > max_compressed_len",
));
}
// check the length of the uncompressed bytes
let len = decompress_len(&raw_message.data)?;
if len > self.max_uncompressed_len {
return Err(Error::new(
ErrorKind::InvalidData,
"ssz_snappy decoded data > MAX_PAYLOAD_SIZE",
));
}
@@ -98,10 +108,10 @@ impl gossipsub::DataTransform for SnappyTransform {
) -> Result<Vec<u8>, std::io::Error> {
// Currently we are not employing topic-based compression. Everything is expected to be
// snappy compressed.
if data.len() > self.max_size_per_message {
if data.len() > self.max_uncompressed_len {
return Err(Error::new(
ErrorKind::InvalidData,
"ssz_snappy Encoded data > GOSSIP_MAX_SIZE",
"ssz_snappy Encoded data > MAX_PAYLOAD_SIZE",
));
}
let mut encoder = Encoder::new();

View File

@@ -5,7 +5,7 @@ mod common;
use common::{build_tracing_subscriber, Protocol};
use lighthouse_network::rpc::{methods::*, RequestType};
use lighthouse_network::service::api_types::AppRequestId;
use lighthouse_network::{rpc::max_rpc_size, NetworkEvent, ReportSource, Response};
use lighthouse_network::{NetworkEvent, ReportSource, Response};
use ssz::Encode;
use ssz_types::VariableList;
use std::sync::Arc;
@@ -15,14 +15,14 @@ use tokio::time::sleep;
use tracing::{debug, warn};
use types::{
BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockBellatrix, BlobSidecar, ChainSpec,
EmptyBlock, Epoch, EthSpec, FixedBytesExtended, ForkContext, ForkName, Hash256, MinimalEthSpec,
EmptyBlock, Epoch, EthSpec, FixedBytesExtended, ForkName, Hash256, MinimalEthSpec,
RuntimeVariableList, Signature, SignedBeaconBlock, Slot,
};
type E = MinimalEthSpec;
/// Bellatrix block with length < max_rpc_size.
fn bellatrix_block_small(fork_context: &ForkContext, spec: &ChainSpec) -> BeaconBlock<E> {
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<_>>());
@@ -30,14 +30,14 @@ fn bellatrix_block_small(fork_context: &ForkContext, spec: &ChainSpec) -> Beacon
block.body.execution_payload.execution_payload.transactions = txs;
let block = BeaconBlock::Bellatrix(block);
assert!(block.ssz_bytes_len() <= max_rpc_size(fork_context, spec.max_chunk_size as usize));
assert!(block.ssz_bytes_len() <= spec.max_payload_size as usize);
block
}
/// Bellatrix block with length > MAX_RPC_SIZE.
/// The max limit for a bellatrix block is in the order of ~16GiB which wouldn't fit in memory.
/// Hence, we generate a bellatrix block just greater than `MAX_RPC_SIZE` to test rejection on the rpc layer.
fn bellatrix_block_large(fork_context: &ForkContext, spec: &ChainSpec) -> BeaconBlock<E> {
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<_>>());
@@ -45,7 +45,7 @@ fn bellatrix_block_large(fork_context: &ForkContext, spec: &ChainSpec) -> Beacon
block.body.execution_payload.execution_payload.transactions = txs;
let block = BeaconBlock::Bellatrix(block);
assert!(block.ssz_bytes_len() > max_rpc_size(fork_context, spec.max_chunk_size as usize));
assert!(block.ssz_bytes_len() > spec.max_payload_size as usize);
block
}
@@ -188,7 +188,7 @@ fn test_tcp_blocks_by_range_chunked_rpc() {
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
let rpc_response_altair = Response::BlocksByRange(Some(Arc::new(signed_full_block)));
let full_block = bellatrix_block_small(&common::fork_context(ForkName::Bellatrix), &spec);
let full_block = bellatrix_block_small(&spec);
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
let rpc_response_bellatrix_small =
Response::BlocksByRange(Some(Arc::new(signed_full_block)));
@@ -442,7 +442,7 @@ fn test_tcp_blocks_by_range_over_limit() {
}));
// BlocksByRange Response
let full_block = bellatrix_block_large(&common::fork_context(ForkName::Bellatrix), &spec);
let full_block = bellatrix_block_large(&spec);
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
let rpc_response_bellatrix_large =
Response::BlocksByRange(Some(Arc::new(signed_full_block)));
@@ -813,7 +813,7 @@ fn test_tcp_blocks_by_root_chunked_rpc() {
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
let rpc_response_altair = Response::BlocksByRoot(Some(Arc::new(signed_full_block)));
let full_block = bellatrix_block_small(&common::fork_context(ForkName::Bellatrix), &spec);
let full_block = bellatrix_block_small(&spec);
let signed_full_block = SignedBeaconBlock::from_block(full_block, Signature::empty());
let rpc_response_bellatrix_small =
Response::BlocksByRoot(Some(Arc::new(signed_full_block)));