Gloas serve envelope rpc (#8896)

Serves envelope by range and by root requests. Added PayloadEnvelopeStreamer so that we dont need to alter upstream code when we introduce blinded payload envelopes.


  


Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com>

Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>

Co-Authored-By: dapplion <35266934+dapplion@users.noreply.github.com>
This commit is contained in:
Eitan Seri-Levi
2026-03-25 15:45:24 +09:00
committed by GitHub
parent 7ffc637eef
commit c7055b604f
26 changed files with 1778 additions and 13 deletions

View File

@@ -590,6 +590,8 @@ impl<E: EthSpec> PeerManager<E> {
Protocol::BlocksByRange => PeerAction::MidToleranceError,
Protocol::BlocksByRoot => PeerAction::MidToleranceError,
Protocol::BlobsByRange => PeerAction::MidToleranceError,
Protocol::PayloadEnvelopesByRange => PeerAction::MidToleranceError,
Protocol::PayloadEnvelopesByRoot => PeerAction::MidToleranceError,
// Lighthouse does not currently make light client requests; therefore, this
// is an unexpected scenario. We do not ban the peer for rate limiting.
Protocol::LightClientBootstrap => return,
@@ -615,6 +617,8 @@ impl<E: EthSpec> PeerManager<E> {
Protocol::Ping => PeerAction::Fatal,
Protocol::BlocksByRange => return,
Protocol::BlocksByRoot => return,
Protocol::PayloadEnvelopesByRange => return,
Protocol::PayloadEnvelopesByRoot => return,
Protocol::BlobsByRange => return,
Protocol::BlobsByRoot => return,
Protocol::DataColumnsByRoot => return,
@@ -638,6 +642,8 @@ impl<E: EthSpec> PeerManager<E> {
Protocol::Ping => PeerAction::LowToleranceError,
Protocol::BlocksByRange => PeerAction::MidToleranceError,
Protocol::BlocksByRoot => PeerAction::MidToleranceError,
Protocol::PayloadEnvelopesByRange => PeerAction::MidToleranceError,
Protocol::PayloadEnvelopesByRoot => PeerAction::MidToleranceError,
Protocol::BlobsByRange => PeerAction::MidToleranceError,
Protocol::BlobsByRoot => PeerAction::MidToleranceError,
Protocol::DataColumnsByRoot => PeerAction::MidToleranceError,

View File

@@ -15,6 +15,7 @@ use std::io::{Read, Write};
use std::marker::PhantomData;
use std::sync::Arc;
use tokio_util::codec::{Decoder, Encoder};
use types::SignedExecutionPayloadEnvelope;
use types::{
BlobSidecar, ChainSpec, DataColumnSidecar, DataColumnsByRootIdentifier, EthSpec, ForkContext,
ForkName, Hash256, LightClientBootstrap, LightClientFinalityUpdate,
@@ -76,6 +77,8 @@ impl<E: EthSpec> SSZSnappyInboundCodec<E> {
},
RpcSuccessResponse::BlocksByRange(res) => res.as_ssz_bytes(),
RpcSuccessResponse::BlocksByRoot(res) => res.as_ssz_bytes(),
RpcSuccessResponse::PayloadEnvelopesByRange(res) => res.as_ssz_bytes(),
RpcSuccessResponse::PayloadEnvelopesByRoot(res) => res.as_ssz_bytes(),
RpcSuccessResponse::BlobsByRange(res) => res.as_ssz_bytes(),
RpcSuccessResponse::BlobsByRoot(res) => res.as_ssz_bytes(),
RpcSuccessResponse::DataColumnsByRoot(res) => res.as_ssz_bytes(),
@@ -356,6 +359,8 @@ impl<E: EthSpec> Encoder<RequestType<E>> for SSZSnappyOutboundCodec<E> {
BlocksByRootRequest::V1(req) => req.block_roots.as_ssz_bytes(),
BlocksByRootRequest::V2(req) => req.block_roots.as_ssz_bytes(),
},
RequestType::PayloadEnvelopesByRange(req) => req.as_ssz_bytes(),
RequestType::PayloadEnvelopesByRoot(req) => req.beacon_block_roots.as_ssz_bytes(),
RequestType::BlobsByRange(req) => req.as_ssz_bytes(),
RequestType::BlobsByRoot(req) => req.blob_ids.as_ssz_bytes(),
RequestType::DataColumnsByRange(req) => req.as_ssz_bytes(),
@@ -548,6 +553,19 @@ fn handle_rpc_request<E: EthSpec>(
)?,
}),
))),
SupportedProtocol::PayloadEnvelopesByRangeV1 => {
Ok(Some(RequestType::PayloadEnvelopesByRange(
PayloadEnvelopesByRangeRequest::from_ssz_bytes(decoded_buffer)?,
)))
}
SupportedProtocol::PayloadEnvelopesByRootV1 => Ok(Some(
RequestType::PayloadEnvelopesByRoot(PayloadEnvelopesByRootRequest {
beacon_block_roots: RuntimeVariableList::from_ssz_bytes(
decoded_buffer,
spec.max_request_payloads(),
)?,
}),
)),
SupportedProtocol::BlobsByRangeV1 => Ok(Some(RequestType::BlobsByRange(
BlobsByRangeRequest::from_ssz_bytes(decoded_buffer)?,
))),
@@ -650,6 +668,48 @@ fn handle_rpc_response<E: EthSpec>(
SupportedProtocol::BlocksByRootV1 => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new(
SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?),
)))),
SupportedProtocol::PayloadEnvelopesByRangeV1 => match fork_name {
Some(fork_name) => {
if fork_name.gloas_enabled() {
Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRange(Arc::new(
SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?,
))))
} else {
Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
"Invalid fork name for payload envelopes by range".to_string(),
))
}
}
None => Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
format!(
"No context bytes provided for {:?} response",
versioned_protocol
),
)),
},
SupportedProtocol::PayloadEnvelopesByRootV1 => match fork_name {
Some(fork_name) => {
if fork_name.gloas_enabled() {
Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRoot(Arc::new(
SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?,
))))
} else {
Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
"Invalid fork name for payload envelopes by root".to_string(),
))
}
}
None => Err(RPCError::ErrorResponse(
RpcErrorResponse::InvalidRequest,
format!(
"No context bytes provided for {:?} response",
versioned_protocol
),
)),
},
SupportedProtocol::BlobsByRangeV1 => match fork_name {
Some(fork_name) => {
if fork_name.deneb_enabled() {
@@ -1260,6 +1320,12 @@ mod tests {
RequestType::BlobsByRange(blbrange) => {
assert_eq!(decoded, RequestType::BlobsByRange(blbrange))
}
RequestType::PayloadEnvelopesByRange(perange) => {
assert_eq!(decoded, RequestType::PayloadEnvelopesByRange(perange))
}
RequestType::PayloadEnvelopesByRoot(peroot) => {
assert_eq!(decoded, RequestType::PayloadEnvelopesByRoot(peroot))
}
RequestType::BlobsByRoot(bbroot) => {
assert_eq!(decoded, RequestType::BlobsByRoot(bbroot))
}

View File

@@ -89,6 +89,8 @@ pub struct RateLimiterConfig {
pub(super) goodbye_quota: Quota,
pub(super) blocks_by_range_quota: Quota,
pub(super) blocks_by_root_quota: Quota,
pub(super) payload_envelopes_by_range_quota: Quota,
pub(super) payload_envelopes_by_root_quota: Quota,
pub(super) blobs_by_range_quota: Quota,
pub(super) blobs_by_root_quota: Quota,
pub(super) data_columns_by_root_quota: Quota,
@@ -111,6 +113,10 @@ impl RateLimiterConfig {
Quota::n_every(NonZeroU64::new(128).unwrap(), 10);
pub const DEFAULT_BLOCKS_BY_ROOT_QUOTA: Quota =
Quota::n_every(NonZeroU64::new(128).unwrap(), 10);
pub const DEFAULT_PAYLOAD_ENVELOPES_BY_RANGE_QUOTA: Quota =
Quota::n_every(NonZeroU64::new(128).unwrap(), 10);
pub const DEFAULT_PAYLOAD_ENVELOPES_BY_ROOT_QUOTA: Quota =
Quota::n_every(NonZeroU64::new(128).unwrap(), 10);
// `DEFAULT_BLOCKS_BY_RANGE_QUOTA` * (target + 1) to account for high usage
pub const DEFAULT_BLOBS_BY_RANGE_QUOTA: Quota =
Quota::n_every(NonZeroU64::new(896).unwrap(), 10);
@@ -137,6 +143,8 @@ impl Default for RateLimiterConfig {
goodbye_quota: Self::DEFAULT_GOODBYE_QUOTA,
blocks_by_range_quota: Self::DEFAULT_BLOCKS_BY_RANGE_QUOTA,
blocks_by_root_quota: Self::DEFAULT_BLOCKS_BY_ROOT_QUOTA,
payload_envelopes_by_range_quota: Self::DEFAULT_PAYLOAD_ENVELOPES_BY_RANGE_QUOTA,
payload_envelopes_by_root_quota: Self::DEFAULT_PAYLOAD_ENVELOPES_BY_ROOT_QUOTA,
blobs_by_range_quota: Self::DEFAULT_BLOBS_BY_RANGE_QUOTA,
blobs_by_root_quota: Self::DEFAULT_BLOBS_BY_ROOT_QUOTA,
data_columns_by_root_quota: Self::DEFAULT_DATA_COLUMNS_BY_ROOT_QUOTA,
@@ -169,6 +177,14 @@ impl Debug for RateLimiterConfig {
.field("goodbye", fmt_q!(&self.goodbye_quota))
.field("blocks_by_range", fmt_q!(&self.blocks_by_range_quota))
.field("blocks_by_root", fmt_q!(&self.blocks_by_root_quota))
.field(
"payload_envelopes_by_range",
fmt_q!(&self.payload_envelopes_by_range_quota),
)
.field(
"payload_envelopes_by_root",
fmt_q!(&self.payload_envelopes_by_root_quota),
)
.field("blobs_by_range", fmt_q!(&self.blobs_by_range_quota))
.field("blobs_by_root", fmt_q!(&self.blobs_by_root_quota))
.field(
@@ -197,6 +213,8 @@ impl FromStr for RateLimiterConfig {
let mut goodbye_quota = None;
let mut blocks_by_range_quota = None;
let mut blocks_by_root_quota = None;
let mut payload_envelopes_by_range_quota = None;
let mut payload_envelopes_by_root_quota = None;
let mut blobs_by_range_quota = None;
let mut blobs_by_root_quota = None;
let mut data_columns_by_root_quota = None;
@@ -214,6 +232,12 @@ impl FromStr for RateLimiterConfig {
Protocol::Goodbye => goodbye_quota = goodbye_quota.or(quota),
Protocol::BlocksByRange => blocks_by_range_quota = blocks_by_range_quota.or(quota),
Protocol::BlocksByRoot => blocks_by_root_quota = blocks_by_root_quota.or(quota),
Protocol::PayloadEnvelopesByRange => {
payload_envelopes_by_range_quota = payload_envelopes_by_range_quota.or(quota)
}
Protocol::PayloadEnvelopesByRoot => {
payload_envelopes_by_root_quota = payload_envelopes_by_root_quota.or(quota)
}
Protocol::BlobsByRange => blobs_by_range_quota = blobs_by_range_quota.or(quota),
Protocol::BlobsByRoot => blobs_by_root_quota = blobs_by_root_quota.or(quota),
Protocol::DataColumnsByRoot => {
@@ -250,6 +274,10 @@ impl FromStr for RateLimiterConfig {
.unwrap_or(Self::DEFAULT_BLOCKS_BY_RANGE_QUOTA),
blocks_by_root_quota: blocks_by_root_quota
.unwrap_or(Self::DEFAULT_BLOCKS_BY_ROOT_QUOTA),
payload_envelopes_by_range_quota: payload_envelopes_by_range_quota
.unwrap_or(Self::DEFAULT_PAYLOAD_ENVELOPES_BY_RANGE_QUOTA),
payload_envelopes_by_root_quota: payload_envelopes_by_root_quota
.unwrap_or(Self::DEFAULT_PAYLOAD_ENVELOPES_BY_ROOT_QUOTA),
blobs_by_range_quota: blobs_by_range_quota
.unwrap_or(Self::DEFAULT_BLOBS_BY_RANGE_QUOTA),
blobs_by_root_quota: blobs_by_root_quota.unwrap_or(Self::DEFAULT_BLOBS_BY_ROOT_QUOTA),

View File

@@ -954,6 +954,35 @@ where
return;
}
}
RequestType::PayloadEnvelopesByRange(request) => {
let max_allowed = spec.max_request_payloads;
if request.count > max_allowed {
self.events_out.push(HandlerEvent::Err(HandlerErr::Inbound {
id: self.current_inbound_substream_id,
proto: Protocol::PayloadEnvelopesByRange,
error: RPCError::InvalidData(format!(
"requested exceeded limit. allowed: {}, requested: {}",
max_allowed, request.count
)),
}));
return;
}
}
RequestType::DataColumnsByRange(request) => {
let max_requested = request.max_requested::<E>();
let max_allowed = spec.max_request_data_column_sidecars;
if max_requested > max_allowed {
self.events_out.push(HandlerEvent::Err(HandlerErr::Inbound {
id: self.current_inbound_substream_id,
proto: Protocol::DataColumnsByRange,
error: RPCError::InvalidData(format!(
"requested exceeded limit. allowed: {}, requested: {}",
max_allowed, max_requested
)),
}));
return;
}
}
_ => {}
};

View File

@@ -17,7 +17,8 @@ use types::light_client::consts::MAX_REQUEST_LIGHT_CLIENT_UPDATES;
use types::{
BlobSidecar, ChainSpec, ColumnIndex, DataColumnSidecar, DataColumnsByRootIdentifier, Epoch,
EthSpec, ForkContext, Hash256, LightClientBootstrap, LightClientFinalityUpdate,
LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock, Slot,
LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock,
SignedExecutionPayloadEnvelope, Slot,
};
/// Maximum length of error message.
@@ -362,6 +363,16 @@ impl BlocksByRangeRequest {
}
}
/// Request a number of execution payload envelopes from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct PayloadEnvelopesByRangeRequest {
/// The starting slot to request execution payload envelopes.
pub start_slot: u64,
/// The number of slots from the start slot.
pub count: u64,
}
/// Request a number of beacon blobs from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BlobsByRangeRequest {
@@ -505,6 +516,29 @@ impl BlocksByRootRequest {
}
}
/// Request a number of execution payload envelopes from a peer.
#[derive(Clone, Debug, PartialEq)]
pub struct PayloadEnvelopesByRootRequest {
/// The list of beacon block roots used to request execution payload envelopes.
pub beacon_block_roots: RuntimeVariableList<Hash256>,
}
impl PayloadEnvelopesByRootRequest {
pub fn new(
beacon_block_roots: Vec<Hash256>,
fork_context: &ForkContext,
) -> Result<Self, String> {
let max_requests_envelopes = fork_context.spec.max_request_payloads();
let beacon_block_roots =
RuntimeVariableList::new(beacon_block_roots, max_requests_envelopes).map_err(|e| {
format!("ExecutionPayloadEnvelopesByRootRequest too many beacon block roots: {e:?}")
})?;
Ok(Self { beacon_block_roots })
}
}
/// Request a number of beacon blocks and blobs from a peer.
#[derive(Clone, Debug, PartialEq)]
pub struct BlobsByRootRequest {
@@ -588,6 +622,13 @@ pub enum RpcSuccessResponse<E: EthSpec> {
/// A response to a get BLOCKS_BY_ROOT request.
BlocksByRoot(Arc<SignedBeaconBlock<E>>),
/// A response to a get EXECUTION_PAYLOAD_ENVELOPES_BY_RANGE request. A None response signifies
/// the end of the batch.
PayloadEnvelopesByRange(Arc<SignedExecutionPayloadEnvelope<E>>),
/// A response to a get EXECUTION_PAYLOAD_ENVELOPES_BY_ROOT request.
PayloadEnvelopesByRoot(Arc<SignedExecutionPayloadEnvelope<E>>),
/// A response to a get BLOBS_BY_RANGE request
BlobsByRange(Arc<BlobSidecar<E>>),
@@ -628,6 +669,12 @@ pub enum ResponseTermination {
/// Blocks by root stream termination.
BlocksByRoot,
/// Execution payload envelopes by range stream termination.
PayloadEnvelopesByRange,
/// Execution payload envelopes by root stream termination.
PayloadEnvelopesByRoot,
/// Blobs by range stream termination.
BlobsByRange,
@@ -649,6 +696,8 @@ impl ResponseTermination {
match self {
ResponseTermination::BlocksByRange => Protocol::BlocksByRange,
ResponseTermination::BlocksByRoot => Protocol::BlocksByRoot,
ResponseTermination::PayloadEnvelopesByRange => Protocol::PayloadEnvelopesByRange,
ResponseTermination::PayloadEnvelopesByRoot => Protocol::PayloadEnvelopesByRoot,
ResponseTermination::BlobsByRange => Protocol::BlobsByRange,
ResponseTermination::BlobsByRoot => Protocol::BlobsByRoot,
ResponseTermination::DataColumnsByRoot => Protocol::DataColumnsByRoot,
@@ -744,6 +793,8 @@ impl<E: EthSpec> RpcSuccessResponse<E> {
RpcSuccessResponse::Status(_) => Protocol::Status,
RpcSuccessResponse::BlocksByRange(_) => Protocol::BlocksByRange,
RpcSuccessResponse::BlocksByRoot(_) => Protocol::BlocksByRoot,
RpcSuccessResponse::PayloadEnvelopesByRange(_) => Protocol::PayloadEnvelopesByRange,
RpcSuccessResponse::PayloadEnvelopesByRoot(_) => Protocol::PayloadEnvelopesByRoot,
RpcSuccessResponse::BlobsByRange(_) => Protocol::BlobsByRange,
RpcSuccessResponse::BlobsByRoot(_) => Protocol::BlobsByRoot,
RpcSuccessResponse::DataColumnsByRoot(_) => Protocol::DataColumnsByRoot,
@@ -762,6 +813,7 @@ impl<E: EthSpec> RpcSuccessResponse<E> {
pub fn slot(&self) -> Option<Slot> {
match self {
Self::BlocksByRange(r) | Self::BlocksByRoot(r) => Some(r.slot()),
Self::PayloadEnvelopesByRoot(r) | Self::PayloadEnvelopesByRange(r) => Some(r.slot()),
Self::BlobsByRange(r) | Self::BlobsByRoot(r) => Some(r.slot()),
Self::DataColumnsByRange(r) | Self::DataColumnsByRoot(r) => Some(r.slot()),
Self::LightClientBootstrap(r) => Some(r.get_slot()),
@@ -812,6 +864,20 @@ impl<E: EthSpec> std::fmt::Display for RpcSuccessResponse<E> {
RpcSuccessResponse::BlocksByRoot(block) => {
write!(f, "BlocksByRoot: Block slot: {}", block.slot())
}
RpcSuccessResponse::PayloadEnvelopesByRange(envelope) => {
write!(
f,
"ExecutionPayloadEnvelopesByRange: Envelope slot: {}",
envelope.slot()
)
}
RpcSuccessResponse::PayloadEnvelopesByRoot(envelope) => {
write!(
f,
"ExecutionPayloadEnvelopesByRoot: Envelope slot: {}",
envelope.slot()
)
}
RpcSuccessResponse::BlobsByRange(blob) => {
write!(f, "BlobsByRange: Blob slot: {}", blob.slot())
}

View File

@@ -22,7 +22,7 @@ use types::{
LightClientBootstrap, LightClientBootstrapAltair, LightClientFinalityUpdate,
LightClientFinalityUpdateAltair, LightClientOptimisticUpdate,
LightClientOptimisticUpdateAltair, LightClientUpdate, MainnetEthSpec, MinimalEthSpec,
SignedBeaconBlock,
SignedBeaconBlock, SignedExecutionPayloadEnvelope,
};
// Note: Hardcoding the `EthSpec` type for `SignedBeaconBlock` as min/max values is
@@ -65,6 +65,12 @@ pub static SIGNED_BEACON_BLOCK_BELLATRIX_MAX: LazyLock<usize> =
+ types::ExecutionPayload::<MainnetEthSpec>::max_execution_payload_bellatrix_size() // adding max size of execution payload (~16gb)
+ ssz::BYTES_PER_LENGTH_OFFSET); // Adding the additional ssz offset for the `ExecutionPayload` field
pub static SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MIN: LazyLock<usize> =
LazyLock::new(SignedExecutionPayloadEnvelope::<MainnetEthSpec>::min_size);
pub static SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MAX: LazyLock<usize> =
LazyLock::new(SignedExecutionPayloadEnvelope::<MainnetEthSpec>::max_size);
pub static BLOB_SIDECAR_SIZE: LazyLock<usize> =
LazyLock::new(BlobSidecar::<MainnetEthSpec>::max_size);
@@ -140,13 +146,30 @@ pub fn rpc_block_limits_by_fork(current_fork: ForkName) -> RpcLimits {
),
// After the merge the max SSZ size of a block is absurdly big. The size is actually
// bound by other constants, so here we default to the bellatrix's max value
_ => RpcLimits::new(
*SIGNED_BEACON_BLOCK_BASE_MIN, // Base block is smaller than altair and bellatrix blocks
*SIGNED_BEACON_BLOCK_BELLATRIX_MAX, // Bellatrix block is larger than base and altair blocks
// After the merge the max SSZ size includes the execution payload.
// Gloas blocks no longer contain the execution payload, but we must
// still accept pre-Gloas blocks during historical sync, so we keep the
// Bellatrix max as the upper bound.
ForkName::Bellatrix
| ForkName::Capella
| ForkName::Deneb
| ForkName::Electra
| ForkName::Fulu
| ForkName::Gloas => RpcLimits::new(
*SIGNED_BEACON_BLOCK_BASE_MIN,
*SIGNED_BEACON_BLOCK_BELLATRIX_MAX,
),
}
}
/// Returns the rpc limits for payload_envelope_by_range and payload_envelope_by_root responses.
pub fn rpc_payload_limits() -> RpcLimits {
RpcLimits::new(
*SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MIN,
*SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MAX,
)
}
fn rpc_light_client_updates_by_range_limits_by_fork(current_fork: ForkName) -> RpcLimits {
let altair_fixed_len = LightClientFinalityUpdateAltair::<MainnetEthSpec>::ssz_fixed_len();
@@ -242,6 +265,12 @@ pub enum Protocol {
/// The `BlobsByRange` protocol name.
#[strum(serialize = "blob_sidecars_by_range")]
BlobsByRange,
/// The `ExecutionPayloadEnvelopesByRoot` protocol name.
#[strum(serialize = "execution_payload_envelopes_by_root")]
PayloadEnvelopesByRoot,
/// The `ExecutionPayloadEnvelopesByRange` protocol name.
#[strum(serialize = "execution_payload_envelopes_by_range")]
PayloadEnvelopesByRange,
/// The `BlobsByRoot` protocol name.
#[strum(serialize = "blob_sidecars_by_root")]
BlobsByRoot,
@@ -277,6 +306,8 @@ impl Protocol {
Protocol::Goodbye => None,
Protocol::BlocksByRange => Some(ResponseTermination::BlocksByRange),
Protocol::BlocksByRoot => Some(ResponseTermination::BlocksByRoot),
Protocol::PayloadEnvelopesByRange => Some(ResponseTermination::PayloadEnvelopesByRange),
Protocol::PayloadEnvelopesByRoot => Some(ResponseTermination::PayloadEnvelopesByRoot),
Protocol::BlobsByRange => Some(ResponseTermination::BlobsByRange),
Protocol::BlobsByRoot => Some(ResponseTermination::BlobsByRoot),
Protocol::DataColumnsByRoot => Some(ResponseTermination::DataColumnsByRoot),
@@ -307,6 +338,8 @@ pub enum SupportedProtocol {
BlocksByRangeV2,
BlocksByRootV1,
BlocksByRootV2,
PayloadEnvelopesByRangeV1,
PayloadEnvelopesByRootV1,
BlobsByRangeV1,
BlobsByRootV1,
DataColumnsByRootV1,
@@ -329,6 +362,8 @@ impl SupportedProtocol {
SupportedProtocol::GoodbyeV1 => "1",
SupportedProtocol::BlocksByRangeV1 => "1",
SupportedProtocol::BlocksByRangeV2 => "2",
SupportedProtocol::PayloadEnvelopesByRangeV1 => "1",
SupportedProtocol::PayloadEnvelopesByRootV1 => "1",
SupportedProtocol::BlocksByRootV1 => "1",
SupportedProtocol::BlocksByRootV2 => "2",
SupportedProtocol::BlobsByRangeV1 => "1",
@@ -355,6 +390,8 @@ impl SupportedProtocol {
SupportedProtocol::BlocksByRangeV2 => Protocol::BlocksByRange,
SupportedProtocol::BlocksByRootV1 => Protocol::BlocksByRoot,
SupportedProtocol::BlocksByRootV2 => Protocol::BlocksByRoot,
SupportedProtocol::PayloadEnvelopesByRangeV1 => Protocol::PayloadEnvelopesByRange,
SupportedProtocol::PayloadEnvelopesByRootV1 => Protocol::PayloadEnvelopesByRoot,
SupportedProtocol::BlobsByRangeV1 => Protocol::BlobsByRange,
SupportedProtocol::BlobsByRootV1 => Protocol::BlobsByRoot,
SupportedProtocol::DataColumnsByRootV1 => Protocol::DataColumnsByRoot,
@@ -409,6 +446,18 @@ impl SupportedProtocol {
ProtocolId::new(SupportedProtocol::DataColumnsByRangeV1, Encoding::SSZSnappy),
]);
}
if fork_context.fork_exists(ForkName::Gloas) {
supported.extend_from_slice(&[
ProtocolId::new(
SupportedProtocol::PayloadEnvelopesByRangeV1,
Encoding::SSZSnappy,
),
ProtocolId::new(
SupportedProtocol::PayloadEnvelopesByRootV1,
Encoding::SSZSnappy,
),
]);
}
supported
}
}
@@ -511,6 +560,13 @@ impl ProtocolId {
<OldBlocksByRangeRequestV2 as Encode>::ssz_fixed_len(),
),
Protocol::BlocksByRoot => RpcLimits::new(0, spec.max_blocks_by_root_request),
Protocol::PayloadEnvelopesByRange => RpcLimits::new(
<PayloadEnvelopesByRangeRequest as Encode>::ssz_fixed_len(),
<PayloadEnvelopesByRangeRequest as Encode>::ssz_fixed_len(),
),
Protocol::PayloadEnvelopesByRoot => {
RpcLimits::new(0, spec.max_payload_envelopes_by_root_request)
}
Protocol::BlobsByRange => RpcLimits::new(
<BlobsByRangeRequest as Encode>::ssz_fixed_len(),
<BlobsByRangeRequest as Encode>::ssz_fixed_len(),
@@ -549,6 +605,8 @@ impl ProtocolId {
Protocol::Goodbye => RpcLimits::new(0, 0), // Goodbye request has no response
Protocol::BlocksByRange => rpc_block_limits_by_fork(fork_context.current_fork_name()),
Protocol::BlocksByRoot => rpc_block_limits_by_fork(fork_context.current_fork_name()),
Protocol::PayloadEnvelopesByRange => rpc_payload_limits(),
Protocol::PayloadEnvelopesByRoot => rpc_payload_limits(),
Protocol::BlobsByRange => rpc_blob_limits::<E>(),
Protocol::BlobsByRoot => rpc_blob_limits::<E>(),
Protocol::DataColumnsByRoot => {
@@ -586,6 +644,8 @@ impl ProtocolId {
match self.versioned_protocol {
SupportedProtocol::BlocksByRangeV2
| SupportedProtocol::BlocksByRootV2
| SupportedProtocol::PayloadEnvelopesByRangeV1
| SupportedProtocol::PayloadEnvelopesByRootV1
| SupportedProtocol::BlobsByRangeV1
| SupportedProtocol::BlobsByRootV1
| SupportedProtocol::DataColumnsByRootV1
@@ -737,6 +797,8 @@ pub enum RequestType<E: EthSpec> {
Goodbye(GoodbyeReason),
BlocksByRange(OldBlocksByRangeRequest),
BlocksByRoot(BlocksByRootRequest),
PayloadEnvelopesByRange(PayloadEnvelopesByRangeRequest),
PayloadEnvelopesByRoot(PayloadEnvelopesByRootRequest),
BlobsByRange(BlobsByRangeRequest),
BlobsByRoot(BlobsByRootRequest),
DataColumnsByRoot(DataColumnsByRootRequest<E>),
@@ -760,6 +822,8 @@ impl<E: EthSpec> RequestType<E> {
RequestType::Goodbye(_) => 0,
RequestType::BlocksByRange(req) => *req.count(),
RequestType::BlocksByRoot(req) => req.block_roots().len() as u64,
RequestType::PayloadEnvelopesByRange(req) => req.count,
RequestType::PayloadEnvelopesByRoot(req) => req.beacon_block_roots.len() as u64,
RequestType::BlobsByRange(req) => req.max_blobs_requested(digest_epoch, spec),
RequestType::BlobsByRoot(req) => req.blob_ids.len() as u64,
RequestType::DataColumnsByRoot(req) => req.max_requested() as u64,
@@ -789,6 +853,8 @@ impl<E: EthSpec> RequestType<E> {
BlocksByRootRequest::V1(_) => SupportedProtocol::BlocksByRootV1,
BlocksByRootRequest::V2(_) => SupportedProtocol::BlocksByRootV2,
},
RequestType::PayloadEnvelopesByRange(_) => SupportedProtocol::PayloadEnvelopesByRangeV1,
RequestType::PayloadEnvelopesByRoot(_) => SupportedProtocol::PayloadEnvelopesByRootV1,
RequestType::BlobsByRange(_) => SupportedProtocol::BlobsByRangeV1,
RequestType::BlobsByRoot(_) => SupportedProtocol::BlobsByRootV1,
RequestType::DataColumnsByRoot(_) => SupportedProtocol::DataColumnsByRootV1,
@@ -820,6 +886,8 @@ impl<E: EthSpec> RequestType<E> {
// variants that have `multiple_responses()` can have values.
RequestType::BlocksByRange(_) => ResponseTermination::BlocksByRange,
RequestType::BlocksByRoot(_) => ResponseTermination::BlocksByRoot,
RequestType::PayloadEnvelopesByRange(_) => ResponseTermination::PayloadEnvelopesByRange,
RequestType::PayloadEnvelopesByRoot(_) => ResponseTermination::PayloadEnvelopesByRoot,
RequestType::BlobsByRange(_) => ResponseTermination::BlobsByRange,
RequestType::BlobsByRoot(_) => ResponseTermination::BlobsByRoot,
RequestType::DataColumnsByRoot(_) => ResponseTermination::DataColumnsByRoot,
@@ -854,6 +922,14 @@ impl<E: EthSpec> RequestType<E> {
ProtocolId::new(SupportedProtocol::BlocksByRootV2, Encoding::SSZSnappy),
ProtocolId::new(SupportedProtocol::BlocksByRootV1, Encoding::SSZSnappy),
],
RequestType::PayloadEnvelopesByRange(_) => vec![ProtocolId::new(
SupportedProtocol::PayloadEnvelopesByRangeV1,
Encoding::SSZSnappy,
)],
RequestType::PayloadEnvelopesByRoot(_) => vec![ProtocolId::new(
SupportedProtocol::PayloadEnvelopesByRootV1,
Encoding::SSZSnappy,
)],
RequestType::BlobsByRange(_) => vec![ProtocolId::new(
SupportedProtocol::BlobsByRangeV1,
Encoding::SSZSnappy,
@@ -905,6 +981,8 @@ impl<E: EthSpec> RequestType<E> {
RequestType::BlocksByRange(_) => false,
RequestType::BlocksByRoot(_) => false,
RequestType::BlobsByRange(_) => false,
RequestType::PayloadEnvelopesByRange(_) => false,
RequestType::PayloadEnvelopesByRoot(_) => false,
RequestType::BlobsByRoot(_) => false,
RequestType::DataColumnsByRoot(_) => false,
RequestType::DataColumnsByRange(_) => false,
@@ -1015,6 +1093,12 @@ impl<E: EthSpec> std::fmt::Display for RequestType<E> {
RequestType::Goodbye(reason) => write!(f, "Goodbye: {}", reason),
RequestType::BlocksByRange(req) => write!(f, "Blocks by range: {}", req),
RequestType::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req),
RequestType::PayloadEnvelopesByRange(req) => {
write!(f, "Payload envelopes by range: {:?}", req)
}
RequestType::PayloadEnvelopesByRoot(req) => {
write!(f, "Payload envelopes by root: {:?}", req)
}
RequestType::BlobsByRange(req) => write!(f, "Blobs by range: {:?}", req),
RequestType::BlobsByRoot(req) => write!(f, "Blobs by root: {:?}", req),
RequestType::DataColumnsByRoot(req) => write!(f, "Data columns by root: {:?}", req),

View File

@@ -109,7 +109,11 @@ pub struct RPCRateLimiter {
blbrange_rl: Limiter<PeerId>,
/// BlobsByRoot rate limiter.
blbroot_rl: Limiter<PeerId>,
/// DataColumnssByRoot rate limiter.
/// PayloadEnvelopesByRange rate limiter.
envrange_rl: Limiter<PeerId>,
/// PayloadEnvelopesByRoot rate limiter.
envroots_rl: Limiter<PeerId>,
/// DataColumnsByRoot rate limiter.
dcbroot_rl: Limiter<PeerId>,
/// DataColumnsByRange rate limiter.
dcbrange_rl: Limiter<PeerId>,
@@ -148,6 +152,10 @@ pub struct RPCRateLimiterBuilder {
bbrange_quota: Option<Quota>,
/// Quota for the BlocksByRoot protocol.
bbroots_quota: Option<Quota>,
/// Quota for the ExecutionPayloadEnvelopesByRange protocol.
perange_quota: Option<Quota>,
/// Quota for the ExecutionPayloadEnvelopesByRoot protocol.
peroots_quota: Option<Quota>,
/// Quota for the BlobsByRange protocol.
blbrange_quota: Option<Quota>,
/// Quota for the BlobsByRoot protocol.
@@ -177,6 +185,8 @@ impl RPCRateLimiterBuilder {
Protocol::Goodbye => self.goodbye_quota = q,
Protocol::BlocksByRange => self.bbrange_quota = q,
Protocol::BlocksByRoot => self.bbroots_quota = q,
Protocol::PayloadEnvelopesByRange => self.perange_quota = q,
Protocol::PayloadEnvelopesByRoot => self.peroots_quota = q,
Protocol::BlobsByRange => self.blbrange_quota = q,
Protocol::BlobsByRoot => self.blbroot_quota = q,
Protocol::DataColumnsByRoot => self.dcbroot_quota = q,
@@ -201,6 +211,12 @@ impl RPCRateLimiterBuilder {
let bbrange_quota = self
.bbrange_quota
.ok_or("BlocksByRange quota not specified")?;
let perange_quota = self
.perange_quota
.ok_or("PayloadEnvelopesByRange quota not specified")?;
let peroots_quota = self
.peroots_quota
.ok_or("PayloadEnvelopesByRoot quota not specified")?;
let lc_bootstrap_quota = self
.lcbootstrap_quota
.ok_or("LightClientBootstrap quota not specified")?;
@@ -236,6 +252,8 @@ impl RPCRateLimiterBuilder {
let goodbye_rl = Limiter::from_quota(goodbye_quota)?;
let bbroots_rl = Limiter::from_quota(bbroots_quota)?;
let bbrange_rl = Limiter::from_quota(bbrange_quota)?;
let envrange_rl = Limiter::from_quota(perange_quota)?;
let envroots_rl = Limiter::from_quota(peroots_quota)?;
let blbrange_rl = Limiter::from_quota(blbrange_quota)?;
let blbroot_rl = Limiter::from_quota(blbroots_quota)?;
let dcbroot_rl = Limiter::from_quota(dcbroot_quota)?;
@@ -259,6 +277,8 @@ impl RPCRateLimiterBuilder {
goodbye_rl,
bbroots_rl,
bbrange_rl,
envrange_rl,
envroots_rl,
blbrange_rl,
blbroot_rl,
dcbroot_rl,
@@ -312,6 +332,8 @@ impl RPCRateLimiter {
goodbye_quota,
blocks_by_range_quota,
blocks_by_root_quota,
payload_envelopes_by_range_quota,
payload_envelopes_by_root_quota,
blobs_by_range_quota,
blobs_by_root_quota,
data_columns_by_root_quota,
@@ -329,6 +351,14 @@ impl RPCRateLimiter {
.set_quota(Protocol::Goodbye, goodbye_quota)
.set_quota(Protocol::BlocksByRange, blocks_by_range_quota)
.set_quota(Protocol::BlocksByRoot, blocks_by_root_quota)
.set_quota(
Protocol::PayloadEnvelopesByRange,
payload_envelopes_by_range_quota,
)
.set_quota(
Protocol::PayloadEnvelopesByRoot,
payload_envelopes_by_root_quota,
)
.set_quota(Protocol::BlobsByRange, blobs_by_range_quota)
.set_quota(Protocol::BlobsByRoot, blobs_by_root_quota)
.set_quota(Protocol::DataColumnsByRoot, data_columns_by_root_quota)
@@ -376,6 +406,8 @@ impl RPCRateLimiter {
Protocol::Goodbye => &mut self.goodbye_rl,
Protocol::BlocksByRange => &mut self.bbrange_rl,
Protocol::BlocksByRoot => &mut self.bbroots_rl,
Protocol::PayloadEnvelopesByRange => &mut self.envrange_rl,
Protocol::PayloadEnvelopesByRoot => &mut self.envroots_rl,
Protocol::BlobsByRange => &mut self.blbrange_rl,
Protocol::BlobsByRoot => &mut self.blbroot_rl,
Protocol::DataColumnsByRoot => &mut self.dcbroot_rl,
@@ -400,6 +432,8 @@ impl RPCRateLimiter {
status_rl,
bbrange_rl,
bbroots_rl,
envrange_rl,
envroots_rl,
blbrange_rl,
blbroot_rl,
dcbroot_rl,
@@ -417,6 +451,8 @@ impl RPCRateLimiter {
status_rl.prune(time_since_start);
bbrange_rl.prune(time_since_start);
bbroots_rl.prune(time_since_start);
envrange_rl.prune(time_since_start);
envroots_rl.prune(time_since_start);
blbrange_rl.prune(time_since_start);
blbroot_rl.prune(time_since_start);
dcbrange_rl.prune(time_since_start);

View File

@@ -5,6 +5,7 @@ use std::sync::Arc;
use types::{
BlobSidecar, DataColumnSidecar, Epoch, EthSpec, LightClientBootstrap,
LightClientFinalityUpdate, LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock,
SignedExecutionPayloadEnvelope,
};
pub type Id = u32;
@@ -160,6 +161,10 @@ pub enum Response<E: EthSpec> {
DataColumnsByRange(Option<Arc<DataColumnSidecar<E>>>),
/// A response to a get BLOCKS_BY_ROOT request.
BlocksByRoot(Option<Arc<SignedBeaconBlock<E>>>),
/// A response to a get `EXECUTION_PAYLOAD_ENVELOPES_BY_ROOT` request.
PayloadEnvelopesByRoot(Option<Arc<SignedExecutionPayloadEnvelope<E>>>),
/// A response to a get `EXECUTION_PAYLOAD_ENVELOPES_BY_RANGE` request.
PayloadEnvelopesByRange(Option<Arc<SignedExecutionPayloadEnvelope<E>>>),
/// A response to a get BLOBS_BY_ROOT request.
BlobsByRoot(Option<Arc<BlobSidecar<E>>>),
/// A response to a get DATA_COLUMN_SIDECARS_BY_ROOT request.
@@ -185,6 +190,16 @@ impl<E: EthSpec> std::convert::From<Response<E>> for RpcResponse<E> {
Some(b) => RpcResponse::Success(RpcSuccessResponse::BlocksByRange(b)),
None => RpcResponse::StreamTermination(ResponseTermination::BlocksByRange),
},
Response::PayloadEnvelopesByRoot(r) => match r {
Some(p) => RpcResponse::Success(RpcSuccessResponse::PayloadEnvelopesByRoot(p)),
None => RpcResponse::StreamTermination(ResponseTermination::PayloadEnvelopesByRoot),
},
Response::PayloadEnvelopesByRange(r) => match r {
Some(p) => RpcResponse::Success(RpcSuccessResponse::PayloadEnvelopesByRange(p)),
None => {
RpcResponse::StreamTermination(ResponseTermination::PayloadEnvelopesByRange)
}
},
Response::BlobsByRoot(r) => match r {
Some(b) => RpcResponse::Success(RpcSuccessResponse::BlobsByRoot(b)),
None => RpcResponse::StreamTermination(ResponseTermination::BlobsByRoot),

View File

@@ -1524,6 +1524,28 @@ impl<E: EthSpec> Network<E> {
request_type,
})
}
RequestType::PayloadEnvelopesByRange(_) => {
metrics::inc_counter_vec(
&metrics::TOTAL_RPC_REQUESTS,
&["payload_envelopes_by_range"],
);
Some(NetworkEvent::RequestReceived {
peer_id,
inbound_request_id,
request_type,
})
}
RequestType::PayloadEnvelopesByRoot(_) => {
metrics::inc_counter_vec(
&metrics::TOTAL_RPC_REQUESTS,
&["payload_envelopes_by_root"],
);
Some(NetworkEvent::RequestReceived {
peer_id,
inbound_request_id,
request_type,
})
}
RequestType::BlobsByRange(_) => {
metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blobs_by_range"]);
Some(NetworkEvent::RequestReceived {
@@ -1638,6 +1660,16 @@ impl<E: EthSpec> Network<E> {
RpcSuccessResponse::BlocksByRoot(resp) => {
self.build_response(id, peer_id, Response::BlocksByRoot(Some(resp)))
}
RpcSuccessResponse::PayloadEnvelopesByRange(resp) => self.build_response(
id,
peer_id,
Response::PayloadEnvelopesByRange(Some(resp)),
),
RpcSuccessResponse::PayloadEnvelopesByRoot(resp) => self.build_response(
id,
peer_id,
Response::PayloadEnvelopesByRoot(Some(resp)),
),
RpcSuccessResponse::BlobsByRoot(resp) => {
self.build_response(id, peer_id, Response::BlobsByRoot(Some(resp)))
}
@@ -1672,6 +1704,12 @@ impl<E: EthSpec> Network<E> {
let response = match termination {
ResponseTermination::BlocksByRange => Response::BlocksByRange(None),
ResponseTermination::BlocksByRoot => Response::BlocksByRoot(None),
ResponseTermination::PayloadEnvelopesByRange => {
Response::PayloadEnvelopesByRange(None)
}
ResponseTermination::PayloadEnvelopesByRoot => {
Response::PayloadEnvelopesByRoot(None)
}
ResponseTermination::BlobsByRange => Response::BlobsByRange(None),
ResponseTermination::BlobsByRoot => Response::BlobsByRoot(None),
ResponseTermination::DataColumnsByRoot => Response::DataColumnsByRoot(None),