From b69bff5ec99c0553d8276043c06230d7a7c8587f Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 10 Sep 2024 16:35:58 -0700 Subject: [PATCH 1/6] enable lc update over rpc --- beacon_node/beacon_processor/src/lib.rs | 13 ++- .../src/peer_manager/mod.rs | 4 + .../lighthouse_network/src/rpc/codec.rs | 5 ++ .../lighthouse_network/src/rpc/config.rs | 10 +++ .../lighthouse_network/src/rpc/methods.rs | 50 +++++++++++ beacon_node/lighthouse_network/src/rpc/mod.rs | 3 + .../lighthouse_network/src/rpc/protocol.rs | 42 ++++++++- .../src/rpc/rate_limiter.rs | 16 ++++ .../src/service/api_types.rs | 10 ++- .../lighthouse_network/src/service/mod.rs | 8 ++ .../network_beacon_processor/rpc_methods.rs | 89 +++++++++++++++++++ beacon_node/network/src/router.rs | 3 +- consensus/types/src/light_client_update.rs | 28 +++++- 13 files changed, 276 insertions(+), 5 deletions(-) diff --git a/beacon_node/beacon_processor/src/lib.rs b/beacon_node/beacon_processor/src/lib.rs index cd5a1d6cff0..32f392b63ce 100644 --- a/beacon_node/beacon_processor/src/lib.rs +++ b/beacon_node/beacon_processor/src/lib.rs @@ -130,6 +130,7 @@ pub struct BeaconProcessorQueueLengths { lc_bootstrap_queue: usize, lc_optimistic_update_queue: usize, lc_finality_update_queue: usize, + lc_update_range_queue: usize, api_request_p0_queue: usize, api_request_p1_queue: usize, } @@ -191,6 +192,7 @@ impl BeaconProcessorQueueLengths { lc_bootstrap_queue: 1024, lc_optimistic_update_queue: 512, lc_finality_update_queue: 512, + lc_update_range_queue: 512, api_request_p0_queue: 1024, api_request_p1_queue: 1024, }) @@ -611,6 +613,7 @@ pub enum Work { LightClientBootstrapRequest(BlockingFn), LightClientOptimisticUpdateRequest(BlockingFn), LightClientFinalityUpdateRequest(BlockingFn), + LightClientUpdatesByRangeRequest(BlockingFn), ApiRequestP0(BlockingOrAsync), ApiRequestP1(BlockingOrAsync), } @@ -662,6 +665,7 @@ pub enum WorkType { LightClientBootstrapRequest, LightClientOptimisticUpdateRequest, LightClientFinalityUpdateRequest, + LightClientUpdatesByRangeRequest, ApiRequestP0, ApiRequestP1, } @@ -712,6 +716,7 @@ impl Work { WorkType::LightClientOptimisticUpdateRequest } Work::LightClientFinalityUpdateRequest(_) => WorkType::LightClientFinalityUpdateRequest, + Work::LightClientUpdatesByRangeRequest(_) => WorkType::LightClientUpdatesByRangeRequest, Work::UnknownBlockAttestation { .. } => WorkType::UnknownBlockAttestation, Work::UnknownBlockAggregate { .. } => WorkType::UnknownBlockAggregate, Work::UnknownBlockSamplingRequest { .. } => WorkType::UnknownBlockSamplingRequest, @@ -891,6 +896,7 @@ impl BeaconProcessor { let mut lc_optimistic_update_queue = FifoQueue::new(queue_lengths.lc_optimistic_update_queue); let mut lc_finality_update_queue = FifoQueue::new(queue_lengths.lc_finality_update_queue); + let mut lc_update_range_queue = FifoQueue::new(queue_lengths.lc_update_range_queue); let mut api_request_p0_queue = FifoQueue::new(queue_lengths.api_request_p0_queue); let mut api_request_p1_queue = FifoQueue::new(queue_lengths.api_request_p1_queue); @@ -1368,6 +1374,9 @@ impl BeaconProcessor { Work::LightClientFinalityUpdateRequest { .. } => { lc_finality_update_queue.push(work, work_id, &self.log) } + Work::LightClientUpdatesByRangeRequest { .. } => { + lc_update_range_queue.push(work, work_id, &self.log) + } Work::UnknownBlockAttestation { .. } => { unknown_block_attestation_queue.push(work) } @@ -1459,6 +1468,7 @@ impl BeaconProcessor { WorkType::LightClientFinalityUpdateRequest => { lc_finality_update_queue.len() } + WorkType::LightClientUpdatesByRangeRequest => lc_update_range_queue.len(), WorkType::ApiRequestP0 => api_request_p0_queue.len(), WorkType::ApiRequestP1 => api_request_p1_queue.len(), }; @@ -1611,7 +1621,8 @@ impl BeaconProcessor { | Work::GossipBlsToExecutionChange(process_fn) | Work::LightClientBootstrapRequest(process_fn) | Work::LightClientOptimisticUpdateRequest(process_fn) - | Work::LightClientFinalityUpdateRequest(process_fn) => { + | Work::LightClientFinalityUpdateRequest(process_fn) + | Work::LightClientUpdatesByRangeRequest(process_fn) => { task_spawner.spawn_blocking(process_fn) } }; diff --git a/beacon_node/lighthouse_network/src/peer_manager/mod.rs b/beacon_node/lighthouse_network/src/peer_manager/mod.rs index 4d913312354..3c8c1f6da03 100644 --- a/beacon_node/lighthouse_network/src/peer_manager/mod.rs +++ b/beacon_node/lighthouse_network/src/peer_manager/mod.rs @@ -567,11 +567,13 @@ impl PeerManager { Protocol::BlocksByRange => PeerAction::MidToleranceError, Protocol::BlocksByRoot => PeerAction::MidToleranceError, Protocol::BlobsByRange => PeerAction::MidToleranceError, + // TODO(lc-update) review this comment and logic // 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, Protocol::LightClientOptimisticUpdate => return, Protocol::LightClientFinalityUpdate => return, + Protocol::LightClientUpdatesByRange => return, Protocol::BlobsByRoot => PeerAction::MidToleranceError, Protocol::DataColumnsByRoot => PeerAction::MidToleranceError, Protocol::DataColumnsByRange => PeerAction::MidToleranceError, @@ -599,6 +601,7 @@ impl PeerManager { Protocol::LightClientBootstrap => return, Protocol::LightClientOptimisticUpdate => return, Protocol::LightClientFinalityUpdate => return, + Protocol::LightClientUpdatesByRange => return, Protocol::MetaData => PeerAction::Fatal, Protocol::Status => PeerAction::Fatal, } @@ -620,6 +623,7 @@ impl PeerManager { Protocol::LightClientBootstrap => return, Protocol::LightClientOptimisticUpdate => return, Protocol::LightClientFinalityUpdate => return, + Protocol::LightClientUpdatesByRange => return, Protocol::Goodbye => return, Protocol::MetaData => return, Protocol::Status => return, diff --git a/beacon_node/lighthouse_network/src/rpc/codec.rs b/beacon_node/lighthouse_network/src/rpc/codec.rs index 224fb8a5f71..b1d9f9e5586 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec.rs @@ -76,6 +76,7 @@ impl SSZSnappyInboundCodec { RPCResponse::LightClientBootstrap(res) => res.as_ssz_bytes(), RPCResponse::LightClientOptimisticUpdate(res) => res.as_ssz_bytes(), RPCResponse::LightClientFinalityUpdate(res) => res.as_ssz_bytes(), + RPCResponse::LightClientUpdatesByRange(res) => res.as_ssz_bytes(), RPCResponse::Pong(res) => res.data.as_ssz_bytes(), RPCResponse::MetaData(res) => // Encode the correct version of the MetaData response based on the negotiated version. @@ -494,6 +495,10 @@ fn context_bytes( return lc_finality_update .map_with_fork_name(|fork_name| fork_context.to_context_bytes(fork_name)); } + RPCResponse::LightClientUpdatesByRange(lc_update) => { + return lc_update + .map_with_fork_name(|fork_name| fork_context.to_context_bytes(fork_name)); + } // These will not pass the has_context_bytes() check RPCResponse::Status(_) | RPCResponse::Pong(_) | RPCResponse::MetaData(_) => { return None; diff --git a/beacon_node/lighthouse_network/src/rpc/config.rs b/beacon_node/lighthouse_network/src/rpc/config.rs index fcb9c986048..42ece6dc4ff 100644 --- a/beacon_node/lighthouse_network/src/rpc/config.rs +++ b/beacon_node/lighthouse_network/src/rpc/config.rs @@ -96,6 +96,7 @@ pub struct RateLimiterConfig { pub(super) light_client_bootstrap_quota: Quota, pub(super) light_client_optimistic_update_quota: Quota, pub(super) light_client_finality_update_quota: Quota, + pub(super) light_client_updates_by_range_quota: Quota, } impl RateLimiterConfig { @@ -121,6 +122,7 @@ impl RateLimiterConfig { pub const DEFAULT_LIGHT_CLIENT_BOOTSTRAP_QUOTA: Quota = Quota::one_every(10); pub const DEFAULT_LIGHT_CLIENT_OPTIMISTIC_UPDATE_QUOTA: Quota = Quota::one_every(10); pub const DEFAULT_LIGHT_CLIENT_FINALITY_UPDATE_QUOTA: Quota = Quota::one_every(10); + pub const DEFAULT_LIGHT_CLIENT_UPDATES_BY_RANGE_QUOTA: Quota = Quota::one_every(10); } impl Default for RateLimiterConfig { @@ -140,6 +142,7 @@ impl Default for RateLimiterConfig { light_client_optimistic_update_quota: Self::DEFAULT_LIGHT_CLIENT_OPTIMISTIC_UPDATE_QUOTA, light_client_finality_update_quota: Self::DEFAULT_LIGHT_CLIENT_FINALITY_UPDATE_QUOTA, + light_client_updates_by_range_quota: Self::DEFAULT_LIGHT_CLIENT_UPDATES_BY_RANGE_QUOTA, } } } @@ -198,6 +201,7 @@ impl FromStr for RateLimiterConfig { let mut light_client_bootstrap_quota = None; let mut light_client_optimistic_update_quota = None; let mut light_client_finality_update_quota = None; + let mut light_client_updates_by_range_quota = None; for proto_def in s.split(';') { let ProtocolQuota { protocol, quota } = proto_def.parse()?; @@ -228,6 +232,10 @@ impl FromStr for RateLimiterConfig { light_client_finality_update_quota = light_client_finality_update_quota.or(quota) } + Protocol::LightClientUpdatesByRange => { + light_client_updates_by_range_quota = + light_client_updates_by_range_quota.or(quota) + } } } Ok(RateLimiterConfig { @@ -252,6 +260,8 @@ impl FromStr for RateLimiterConfig { .unwrap_or(Self::DEFAULT_LIGHT_CLIENT_OPTIMISTIC_UPDATE_QUOTA), light_client_finality_update_quota: light_client_finality_update_quota .unwrap_or(Self::DEFAULT_LIGHT_CLIENT_FINALITY_UPDATE_QUOTA), + light_client_updates_by_range_quota: light_client_updates_by_range_quota + .unwrap_or(Self::DEFAULT_LIGHT_CLIENT_UPDATES_BY_RANGE_QUOTA), }) } } diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index a96b9d1b166..0987cb34434 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -14,6 +14,7 @@ use std::sync::Arc; use strum::IntoStaticStr; use superstruct::superstruct; use types::blob_sidecar::BlobIdentifier; +use types::LightClientUpdate; use types::{ blob_sidecar::BlobSidecar, ChainSpec, ColumnIndex, DataColumnIdentifier, DataColumnSidecar, Epoch, EthSpec, Hash256, LightClientBootstrap, LightClientFinalityUpdate, @@ -477,6 +478,41 @@ impl DataColumnsByRootRequest { } } +/// Request a number of beacon data columns from a peer. +#[derive(Encode, Decode, Clone, Debug, PartialEq)] +pub struct LightClientUpdatesByRangeRequest { + /// The starting period to request light client updates. + pub start_period: u64, + /// The number of periods from `start_period`. + pub count: u64, +} + +impl LightClientUpdatesByRangeRequest { + pub fn max_requested(&self) -> u64 { + // TODO(lc-update) check spec for max request limits + todo!() + } + + pub fn ssz_min_len() -> usize { + LightClientUpdatesByRangeRequest { + start_period: 0, + count: 0, + } + .as_ssz_bytes() + .len() + } + + pub fn ssz_max_len(_: &ChainSpec) -> usize { + // TODO(lc-update) make sure max count is correct + LightClientUpdatesByRangeRequest { + start_period: 0, + count: 0, + } + .as_ssz_bytes() + .len() + } +} + /* RPC Handling and Grouping */ // Collection of enums and structs used by the Codecs to encode/decode RPC messages @@ -504,6 +540,9 @@ pub enum RPCResponse { /// A response to a get LIGHT_CLIENT_FINALITY_UPDATE request. LightClientFinalityUpdate(Arc>), + /// A response to a get LIGHT_CLIENT_UPDATES_BY_RANGE request. + LightClientUpdatesByRange(Arc>), + /// A response to a get BLOBS_BY_ROOT request. BlobsByRoot(Arc>), @@ -540,6 +579,9 @@ pub enum ResponseTermination { /// Data column sidecars by range stream termination. DataColumnsByRange, + + /// Light client updates by range stream termination. + LightClientUpdatesByRange, } /// The structured response containing a result/code indicating success or failure @@ -637,6 +679,7 @@ impl RPCResponse { RPCResponse::LightClientBootstrap(_) => Protocol::LightClientBootstrap, RPCResponse::LightClientOptimisticUpdate(_) => Protocol::LightClientOptimisticUpdate, RPCResponse::LightClientFinalityUpdate(_) => Protocol::LightClientFinalityUpdate, + RPCResponse::LightClientUpdatesByRange(_) => Protocol::LightClientUpdatesByRange, } } } @@ -706,6 +749,13 @@ impl std::fmt::Display for RPCResponse { update.signature_slot() ) } + RPCResponse::LightClientUpdatesByRange(update) => { + write!( + f, + "LightClientUpdatesByRange Slot: {}", + update.signature_slot(), + ) + } } } } diff --git a/beacon_node/lighthouse_network/src/rpc/mod.rs b/beacon_node/lighthouse_network/src/rpc/mod.rs index cd591554a36..4b894a049ad 100644 --- a/beacon_node/lighthouse_network/src/rpc/mod.rs +++ b/beacon_node/lighthouse_network/src/rpc/mod.rs @@ -479,6 +479,9 @@ where ResponseTermination::BlobsByRoot => Protocol::BlobsByRoot, ResponseTermination::DataColumnsByRoot => Protocol::DataColumnsByRoot, ResponseTermination::DataColumnsByRange => Protocol::DataColumnsByRange, + ResponseTermination::LightClientUpdatesByRange => { + Protocol::LightClientUpdatesByRange + } }, ), }; diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index 09a18e5de6b..f082b645605 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -21,7 +21,8 @@ use types::{ BlobSidecar, ChainSpec, DataColumnSidecar, EmptyBlock, EthSpec, ForkContext, ForkName, LightClientBootstrap, LightClientBootstrapAltair, LightClientFinalityUpdate, LightClientFinalityUpdateAltair, LightClientOptimisticUpdate, - LightClientOptimisticUpdateAltair, MainnetEthSpec, Signature, SignedBeaconBlock, + LightClientOptimisticUpdateAltair, LightClientUpdate, MainnetEthSpec, Signature, + SignedBeaconBlock, }; // Note: Hardcoding the `EthSpec` type for `SignedBeaconBlock` as min/max values is @@ -143,6 +144,13 @@ pub static LIGHT_CLIENT_BOOTSTRAP_ELECTRA_MAX: LazyLock = LazyLock::new(| LightClientBootstrap::::ssz_max_len_for_fork(ForkName::Electra) }); +pub static LIGHT_CLIENT_UPDATES_BY_RANGE_CAPELLA_MAX: LazyLock = + LazyLock::new(|| LightClientUpdate::::ssz_max_len_for_fork(ForkName::Capella)); +pub static LIGHT_CLIENT_UPDATES_BY_RANGE_DENEB_MAX: LazyLock = + LazyLock::new(|| LightClientUpdate::::ssz_max_len_for_fork(ForkName::Deneb)); +pub static LIGHT_CLIENT_UPDATES_BY_RANGE_ELECTRA_MAX: LazyLock = + LazyLock::new(|| LightClientUpdate::::ssz_max_len_for_fork(ForkName::Electra)); + /// The protocol prefix the RPC protocol id. const PROTOCOL_PREFIX: &str = "/eth2/beacon_chain/req"; /// The number of seconds to wait for the first bytes of a request once a protocol has been @@ -192,6 +200,26 @@ pub fn rpc_block_limits_by_fork(current_fork: ForkName) -> RpcLimits { } } +fn rpc_light_client_updates_by_range_limits_by_fork(current_fork: ForkName) -> RpcLimits { + let altair_fixed_len = LightClientFinalityUpdateAltair::::ssz_fixed_len(); + + match ¤t_fork { + ForkName::Base => RpcLimits::new(0, 0), + ForkName::Altair | ForkName::Bellatrix => { + RpcLimits::new(altair_fixed_len, altair_fixed_len) + } + ForkName::Capella => { + RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_UPDATES_BY_RANGE_CAPELLA_MAX) + } + ForkName::Deneb => { + RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_UPDATES_BY_RANGE_DENEB_MAX) + } + ForkName::Electra => { + RpcLimits::new(altair_fixed_len, *LIGHT_CLIENT_UPDATES_BY_RANGE_ELECTRA_MAX) + } + } +} + fn rpc_light_client_finality_update_limits_by_fork(current_fork: ForkName) -> RpcLimits { let altair_fixed_len = LightClientFinalityUpdateAltair::::ssz_fixed_len(); @@ -288,6 +316,9 @@ pub enum Protocol { /// The `LightClientFinalityUpdate` protocol name. #[strum(serialize = "light_client_finality_update")] LightClientFinalityUpdate, + /// The `LightClientUpdatesByRange` protocol name + #[strum(serialize = "light_client_updates_by_range")] + LightClientUpdatesByRange, } impl Protocol { @@ -306,6 +337,7 @@ impl Protocol { Protocol::LightClientBootstrap => None, Protocol::LightClientOptimisticUpdate => None, Protocol::LightClientFinalityUpdate => None, + Protocol::LightClientUpdatesByRange => None, } } } @@ -542,8 +574,13 @@ impl ProtocolId { ::ssz_fixed_len(), ::ssz_fixed_len(), ), + // TODO(lc-update) make sure rpc limits are set correctly for lc data Protocol::LightClientOptimisticUpdate => RpcLimits::new(0, 0), Protocol::LightClientFinalityUpdate => RpcLimits::new(0, 0), + Protocol::LightClientUpdatesByRange => RpcLimits::new( + LightClientUpdatesByRangeRequest::ssz_min_len(), + LightClientUpdatesByRangeRequest::ssz_max_len(spec), + ), Protocol::MetaData => RpcLimits::new(0, 0), // Metadata requests are empty } } @@ -579,6 +616,9 @@ impl ProtocolId { Protocol::LightClientFinalityUpdate => { rpc_light_client_finality_update_limits_by_fork(fork_context.current_fork()) } + Protocol::LightClientUpdatesByRange => { + rpc_light_client_updates_by_range_limits_by_fork(fork_context.current_fork()) + } } } diff --git a/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs b/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs index 523b891a009..9b8de8954f3 100644 --- a/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs +++ b/beacon_node/lighthouse_network/src/rpc/rate_limiter.rs @@ -107,6 +107,8 @@ pub struct RPCRateLimiter { lc_optimistic_update_rl: Limiter, /// LightClientFinalityUpdate rate limiter. lc_finality_update_rl: Limiter, + /// LightClientUpdatesByRange rate limiter. + lc_updates_by_range_rl: Limiter, } /// Error type for non conformant requests @@ -147,6 +149,8 @@ pub struct RPCRateLimiterBuilder { lc_optimistic_update_quota: Option, /// Quota for the LightClientOptimisticUpdate protocol. lc_finality_update_quota: Option, + /// Quota for the LightClientUpdatesByRange protocol. + lc_updates_by_range_quota: Option, } impl RPCRateLimiterBuilder { @@ -167,6 +171,7 @@ impl RPCRateLimiterBuilder { Protocol::LightClientBootstrap => self.lcbootstrap_quota = q, Protocol::LightClientOptimisticUpdate => self.lc_optimistic_update_quota = q, Protocol::LightClientFinalityUpdate => self.lc_finality_update_quota = q, + Protocol::LightClientUpdatesByRange => self.lc_updates_by_range_quota = q, } self } @@ -192,6 +197,9 @@ impl RPCRateLimiterBuilder { let lc_finality_update_quota = self .lc_finality_update_quota .ok_or("LightClientFinalityUpdate quota not specified")?; + let lc_updates_by_range_quota = self + .lc_updates_by_range_quota + .ok_or("LightClientUpdatesByRange quota not specified")?; let blbrange_quota = self .blbrange_quota @@ -222,6 +230,7 @@ impl RPCRateLimiterBuilder { let lc_bootstrap_rl = Limiter::from_quota(lc_bootstrap_quota)?; let lc_optimistic_update_rl = Limiter::from_quota(lc_optimistic_update_quota)?; let lc_finality_update_rl = Limiter::from_quota(lc_finality_update_quota)?; + let lc_updates_by_range_rl = Limiter::from_quota(lc_updates_by_range_quota)?; // check for peers to prune every 30 seconds, starting in 30 seconds let prune_every = tokio::time::Duration::from_secs(30); @@ -242,6 +251,7 @@ impl RPCRateLimiterBuilder { lc_bootstrap_rl, lc_optimistic_update_rl, lc_finality_update_rl, + lc_updates_by_range_rl, init_time: Instant::now(), }) } @@ -288,6 +298,7 @@ impl RPCRateLimiter { light_client_bootstrap_quota, light_client_optimistic_update_quota, light_client_finality_update_quota, + light_client_updates_by_range_quota, } = config; Self::builder() @@ -310,6 +321,10 @@ impl RPCRateLimiter { Protocol::LightClientFinalityUpdate, light_client_finality_update_quota, ) + .set_quota( + Protocol::LightClientUpdatesByRange, + light_client_updates_by_range_quota, + ) .build() } @@ -342,6 +357,7 @@ impl RPCRateLimiter { Protocol::LightClientBootstrap => &mut self.lc_bootstrap_rl, Protocol::LightClientOptimisticUpdate => &mut self.lc_optimistic_update_rl, Protocol::LightClientFinalityUpdate => &mut self.lc_finality_update_rl, + Protocol::LightClientUpdatesByRange => &mut self.lc_updates_by_range_rl, }; check(limiter) } diff --git a/beacon_node/lighthouse_network/src/service/api_types.rs b/beacon_node/lighthouse_network/src/service/api_types.rs index 30400db3b66..ad3f2dc324d 100644 --- a/beacon_node/lighthouse_network/src/service/api_types.rs +++ b/beacon_node/lighthouse_network/src/service/api_types.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use libp2p::swarm::ConnectionId; use types::{ BlobSidecar, DataColumnSidecar, EthSpec, Hash256, LightClientBootstrap, - LightClientFinalityUpdate, LightClientOptimisticUpdate, SignedBeaconBlock, + LightClientFinalityUpdate, LightClientOptimisticUpdate, LightClientUpdate, SignedBeaconBlock, }; use crate::rpc::methods::{ @@ -184,6 +184,8 @@ pub enum Response { LightClientOptimisticUpdate(Arc>), /// A response to a LightClientFinalityUpdate request. LightClientFinalityUpdate(Arc>), + /// A response to a LightClientUpdatesByRange request. + LightClientUpdatesByRange(Option>>), } impl std::convert::From> for RPCCodedResponse { @@ -225,6 +227,12 @@ impl std::convert::From> for RPCCodedResponse { Response::LightClientFinalityUpdate(f) => { RPCCodedResponse::Success(RPCResponse::LightClientFinalityUpdate(f)) } + Response::LightClientUpdatesByRange(f) => match f { + Some(d) => RPCCodedResponse::Success(RPCResponse::LightClientUpdatesByRange(d)), + None => RPCCodedResponse::StreamTermination( + ResponseTermination::LightClientUpdatesByRange, + ), + }, } } } diff --git a/beacon_node/lighthouse_network/src/service/mod.rs b/beacon_node/lighthouse_network/src/service/mod.rs index d97b52f79f1..963f4e102a3 100644 --- a/beacon_node/lighthouse_network/src/service/mod.rs +++ b/beacon_node/lighthouse_network/src/service/mod.rs @@ -1638,6 +1638,11 @@ impl Network { peer_id, Response::LightClientFinalityUpdate(update), ), + RPCResponse::LightClientUpdatesByRange(update) => self.build_response( + id, + peer_id, + Response::LightClientUpdatesByRange(Some(update)), + ), } } HandlerEvent::Ok(RPCReceived::EndOfStream(id, termination)) => { @@ -1648,6 +1653,9 @@ impl Network { ResponseTermination::BlobsByRoot => Response::BlobsByRoot(None), ResponseTermination::DataColumnsByRoot => Response::DataColumnsByRoot(None), ResponseTermination::DataColumnsByRange => Response::DataColumnsByRange(None), + ResponseTermination::LightClientUpdatesByRange => { + Response::LightClientUpdatesByRange(None) + } }; self.build_response(id, peer_id, response) } diff --git a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs index 0c98f5c17e5..ddfe6c623ed 100644 --- a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs @@ -9,6 +9,7 @@ use lighthouse_network::rpc::methods::{ }; use lighthouse_network::rpc::*; use lighthouse_network::{PeerId, PeerRequestId, ReportSource, Response, SyncInfo}; +use methods::LightClientUpdatesByRangeRequest; use slog::{debug, error, warn}; use slot_clock::SlotClock; use std::collections::{hash_map::Entry, HashMap}; @@ -380,6 +381,94 @@ impl NetworkBeaconProcessor { Ok(()) } + pub async fn handle_light_client_updates_by_range( + self: &Arc, + peer_id: PeerId, + request_id: PeerRequestId, + request: LightClientUpdatesByRangeRequest, + ) { + self.terminate_response_stream( + peer_id, + request_id, + self.clone() + .handle_light_client_updates_by_range_request_inner(peer_id, request_id, request) + .await, + Response::BlocksByRange, + ); + } + + /// Handle a `LightClientUpdatesByRange` request from the peer. + pub async fn handle_light_client_updates_by_range_request_inner( + self: Arc, + peer_id: PeerId, + request_id: PeerRequestId, + req: LightClientUpdatesByRangeRequest, + ) -> Result<(), (RPCResponseErrorCode, &'static str)> { + debug!(self.log, "Received LightClientUpdatesByRange Request"; + "peer_id" => %peer_id, + "count" => req.count, + "start_period" => req.start_period, + ); + + // TODO(lc-update) use correct val here + // Should not send more than max light client updates + let max_request_size: u64 = 1; + if req.count > max_request_size { + return Err(( + RPCResponseErrorCode::InvalidRequest, + "Request exceeded max size", + )); + } + + let lc_updates = match self + .chain + .get_light_client_updates(req.start_period, req.count) + { + Ok(lc_updates) => lc_updates, + Err(e) => { + error!(self.log, "Unable to obtain light client updates"; + "request" => ?req, + "peer" => %peer_id, + "error" => ?e + ); + return Err((RPCResponseErrorCode::ServerError, "Database error")); + } + }; + + lc_updates.iter().for_each(|lc_update| { + self.send_network_message(NetworkMessage::SendResponse { + peer_id, + response: Response::LightClientUpdatesByRange(Some(Arc::new(lc_update.clone()))), + id: request_id, + }); + }); + + let lc_updates_sent = lc_updates.len(); + + if lc_updates_sent < req.count as usize { + debug!( + self.log, + "LightClientUpdatesByRange outgoing response processed"; + "peer" => %peer_id, + "msg" => "Failed to return all requested light client updates", + "start_period" => req.start_period, + "requested" => req.count, + "returned" => lc_updates_sent + ); + } else { + debug!( + self.log, + "LightClientUpdatesByRange outgoing response processed"; + "peer" => %peer_id, + "start_period" => req.start_period, + "requested" => req.count, + "returned" => lc_updates_sent + ); + } + + Ok(()) + } + /// Handle a `LightClientBootstrap` request from the peer. pub fn handle_light_client_bootstrap( self: &Arc, diff --git a/beacon_node/network/src/router.rs b/beacon_node/network/src/router.rs index 26c1d14f020..6d168f2eb09 100644 --- a/beacon_node/network/src/router.rs +++ b/beacon_node/network/src/router.rs @@ -275,7 +275,8 @@ impl Router { // Light client responses should not be received Response::LightClientBootstrap(_) | Response::LightClientOptimisticUpdate(_) - | Response::LightClientFinalityUpdate(_) => unreachable!(), + | Response::LightClientFinalityUpdate(_) + | Response::LightClientUpdatesByRange(_) => unreachable!(), } } diff --git a/consensus/types/src/light_client_update.rs b/consensus/types/src/light_client_update.rs index 3b48a68df31..f7a4e268d77 100644 --- a/consensus/types/src/light_client_update.rs +++ b/consensus/types/src/light_client_update.rs @@ -1,5 +1,6 @@ use super::{EthSpec, FixedVector, Hash256, Slot, SyncAggregate, SyncCommittee}; use crate::light_client_header::LightClientHeaderElectra; +use crate::LightClientHeader; use crate::{ beacon_state, test_utils::TestRandom, ChainSpec, Epoch, ForkName, ForkVersionDeserialize, LightClientHeaderAltair, LightClientHeaderCapella, LightClientHeaderDeneb, @@ -10,7 +11,7 @@ use safe_arith::ArithError; use safe_arith::SafeArith; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value; -use ssz::Decode; +use ssz::{Decode, Encode}; use ssz_derive::Decode; use ssz_derive::Encode; use ssz_types::typenum::{U4, U5, U6}; @@ -403,6 +404,31 @@ impl LightClientUpdate { } true } + + // TODO(lc-update) does this math look correct? + #[allow(clippy::arithmetic_side_effects)] + pub fn ssz_max_len_for_fork(fork_name: ForkName) -> usize { + let fixed_len = match fork_name { + ForkName::Base | ForkName::Bellatrix => 0, + ForkName::Altair => as Encode>::ssz_fixed_len(), + ForkName::Capella => as Encode>::ssz_fixed_len(), + ForkName::Deneb => as Encode>::ssz_fixed_len(), + ForkName::Electra => as Encode>::ssz_fixed_len(), + }; + fixed_len + 2 * LightClientHeader::::ssz_max_var_len_for_fork(fork_name) + } + + pub fn map_with_fork_name(&self, func: F) -> R + where + F: Fn(ForkName) -> R, + { + match self { + Self::Altair(_) => func(ForkName::Altair), + Self::Capella(_) => func(ForkName::Capella), + Self::Deneb(_) => func(ForkName::Deneb), + Self::Electra(_) => func(ForkName::Electra), + } + } } fn compute_sync_committee_period_at_slot( From 5c99a38fb5b0369b1cf64cafe1292d5a5472863a Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Thu, 12 Sep 2024 10:07:02 -0700 Subject: [PATCH 2/6] resolve TODOs --- .../src/peer_manager/mod.rs | 1 - .../lighthouse_network/src/rpc/codec.rs | 23 ++++++++++++++++--- .../lighthouse_network/src/rpc/methods.rs | 10 ++++---- .../lighthouse_network/src/rpc/protocol.rs | 18 ++++++++++++--- .../src/service/api_types.rs | 7 +++++- .../lighthouse_network/src/service/mod.rs | 12 ++++++++++ .../src/network_beacon_processor/mod.rs | 18 +++++++++++++++ .../network_beacon_processor/rpc_methods.rs | 20 ++++++++-------- beacon_node/network/src/router.rs | 5 ++++ consensus/types/src/light_client_update.rs | 3 ++- 10 files changed, 93 insertions(+), 24 deletions(-) diff --git a/beacon_node/lighthouse_network/src/peer_manager/mod.rs b/beacon_node/lighthouse_network/src/peer_manager/mod.rs index 3c8c1f6da03..9cf74ccc64e 100644 --- a/beacon_node/lighthouse_network/src/peer_manager/mod.rs +++ b/beacon_node/lighthouse_network/src/peer_manager/mod.rs @@ -567,7 +567,6 @@ impl PeerManager { Protocol::BlocksByRange => PeerAction::MidToleranceError, Protocol::BlocksByRoot => PeerAction::MidToleranceError, Protocol::BlobsByRange => PeerAction::MidToleranceError, - // TODO(lc-update) review this comment and logic // 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, diff --git a/beacon_node/lighthouse_network/src/rpc/codec.rs b/beacon_node/lighthouse_network/src/rpc/codec.rs index b1d9f9e5586..3cf8d8e34cf 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec.rs @@ -18,9 +18,9 @@ use tokio_util::codec::{Decoder, Encoder}; use types::{ BlobSidecar, ChainSpec, DataColumnSidecar, EthSpec, ForkContext, ForkName, Hash256, LightClientBootstrap, LightClientFinalityUpdate, LightClientOptimisticUpdate, - RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockAltair, SignedBeaconBlockBase, - SignedBeaconBlockBellatrix, SignedBeaconBlockCapella, SignedBeaconBlockDeneb, - SignedBeaconBlockElectra, + LightClientUpdate, RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockAltair, + SignedBeaconBlockBase, SignedBeaconBlockBellatrix, SignedBeaconBlockCapella, + SignedBeaconBlockDeneb, SignedBeaconBlockElectra, }; use unsigned_varint::codec::Uvi; @@ -607,6 +607,11 @@ fn handle_rpc_request( SupportedProtocol::LightClientFinalityUpdateV1 => { Ok(Some(InboundRequest::LightClientFinalityUpdate)) } + SupportedProtocol::LightClientUpdatesByRangeV1 => { + Ok(Some(InboundRequest::LightClientUpdatesByRange( + LightClientUpdatesByRangeRequest::from_ssz_bytes(decoded_buffer)?, + ))) + } // MetaData requests return early from InboundUpgrade and do not reach the decoder. // Handle this case just for completeness. SupportedProtocol::MetaDataV3 => { @@ -781,6 +786,18 @@ fn handle_rpc_response( ), )), }, + SupportedProtocol::LightClientUpdatesByRangeV1 => match fork_name { + Some(fork_name) => Ok(Some(RPCResponse::LightClientUpdatesByRange(Arc::new( + LightClientUpdate::from_ssz_bytes(decoded_buffer, &fork_name)?, + )))), + None => Err(RPCError::ErrorResponse( + RPCResponseErrorCode::InvalidRequest, + format!( + "No context bytes provided for {:?} response", + versioned_protocol + ), + )), + }, // MetaData V2/V3 responses have no context bytes, so behave similarly to V1 responses SupportedProtocol::MetaDataV3 => Ok(Some(RPCResponse::MetaData(MetaData::V3( MetaDataV3::from_ssz_bytes(decoded_buffer)?, diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index 0987cb34434..7ea41393c44 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -25,6 +25,10 @@ use types::{ pub type MaxErrorLen = U256; pub const MAX_ERROR_LEN: u64 = 256; +// Max light client updates by range request limits +// spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#configuration +pub const MAX_REQUEST_LIGHT_CLIENT_UPDATES: u64 = 128; + /// Wrapper over SSZ List to represent error message in rpc responses. #[derive(Debug, Clone)] pub struct ErrorType(pub VariableList); @@ -489,8 +493,7 @@ pub struct LightClientUpdatesByRangeRequest { impl LightClientUpdatesByRangeRequest { pub fn max_requested(&self) -> u64 { - // TODO(lc-update) check spec for max request limits - todo!() + MAX_REQUEST_LIGHT_CLIENT_UPDATES } pub fn ssz_min_len() -> usize { @@ -502,8 +505,7 @@ impl LightClientUpdatesByRangeRequest { .len() } - pub fn ssz_max_len(_: &ChainSpec) -> usize { - // TODO(lc-update) make sure max count is correct + pub fn ssz_max_len() -> usize { LightClientUpdatesByRangeRequest { start_period: 0, count: 0, diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index f082b645605..06865a9b37c 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -368,6 +368,7 @@ pub enum SupportedProtocol { LightClientBootstrapV1, LightClientOptimisticUpdateV1, LightClientFinalityUpdateV1, + LightClientUpdatesByRangeV1, } impl SupportedProtocol { @@ -390,6 +391,7 @@ impl SupportedProtocol { SupportedProtocol::LightClientBootstrapV1 => "1", SupportedProtocol::LightClientOptimisticUpdateV1 => "1", SupportedProtocol::LightClientFinalityUpdateV1 => "1", + SupportedProtocol::LightClientUpdatesByRangeV1 => "1", } } @@ -414,6 +416,7 @@ impl SupportedProtocol { Protocol::LightClientOptimisticUpdate } SupportedProtocol::LightClientFinalityUpdateV1 => Protocol::LightClientFinalityUpdate, + SupportedProtocol::LightClientUpdatesByRangeV1 => Protocol::LightClientUpdatesByRange, } } @@ -574,12 +577,11 @@ impl ProtocolId { ::ssz_fixed_len(), ::ssz_fixed_len(), ), - // TODO(lc-update) make sure rpc limits are set correctly for lc data Protocol::LightClientOptimisticUpdate => RpcLimits::new(0, 0), Protocol::LightClientFinalityUpdate => RpcLimits::new(0, 0), Protocol::LightClientUpdatesByRange => RpcLimits::new( LightClientUpdatesByRangeRequest::ssz_min_len(), - LightClientUpdatesByRangeRequest::ssz_max_len(spec), + LightClientUpdatesByRangeRequest::ssz_max_len(), ), Protocol::MetaData => RpcLimits::new(0, 0), // Metadata requests are empty } @@ -634,7 +636,8 @@ impl ProtocolId { | SupportedProtocol::DataColumnsByRangeV1 | SupportedProtocol::LightClientBootstrapV1 | SupportedProtocol::LightClientOptimisticUpdateV1 - | SupportedProtocol::LightClientFinalityUpdateV1 => true, + | SupportedProtocol::LightClientFinalityUpdateV1 + | SupportedProtocol::LightClientUpdatesByRangeV1 => true, SupportedProtocol::StatusV1 | SupportedProtocol::BlocksByRootV1 | SupportedProtocol::BlocksByRangeV1 @@ -765,6 +768,7 @@ pub enum InboundRequest { LightClientBootstrap(LightClientBootstrapRequest), LightClientOptimisticUpdate, LightClientFinalityUpdate, + LightClientUpdatesByRange(LightClientUpdatesByRangeRequest), Ping(Ping), MetaData(MetadataRequest), } @@ -789,6 +793,7 @@ impl InboundRequest { InboundRequest::LightClientBootstrap(_) => 1, InboundRequest::LightClientOptimisticUpdate => 1, InboundRequest::LightClientFinalityUpdate => 1, + InboundRequest::LightClientUpdatesByRange(_) => MAX_REQUEST_LIGHT_CLIENT_UPDATES, } } @@ -822,6 +827,9 @@ impl InboundRequest { InboundRequest::LightClientFinalityUpdate => { SupportedProtocol::LightClientFinalityUpdateV1 } + InboundRequest::LightClientUpdatesByRange(_) => { + SupportedProtocol::LightClientUpdatesByRangeV1 + } } } @@ -844,6 +852,7 @@ impl InboundRequest { InboundRequest::LightClientBootstrap(_) => unreachable!(), InboundRequest::LightClientFinalityUpdate => unreachable!(), InboundRequest::LightClientOptimisticUpdate => unreachable!(), + InboundRequest::LightClientUpdatesByRange(_) => unreachable!(), } } } @@ -962,6 +971,9 @@ impl std::fmt::Display for InboundRequest { InboundRequest::LightClientFinalityUpdate => { write!(f, "Light client finality update request") } + InboundRequest::LightClientUpdatesByRange(_) => { + write!(f, "Light client updates by range request") + } } } } diff --git a/beacon_node/lighthouse_network/src/service/api_types.rs b/beacon_node/lighthouse_network/src/service/api_types.rs index ad3f2dc324d..fd8624495df 100644 --- a/beacon_node/lighthouse_network/src/service/api_types.rs +++ b/beacon_node/lighthouse_network/src/service/api_types.rs @@ -18,6 +18,8 @@ use crate::rpc::{ OutboundRequest, SubstreamId, }; +use super::methods::LightClientUpdatesByRangeRequest; + /// Identifier of requests sent by a peer. pub type PeerRequestId = (ConnectionId, SubstreamId); @@ -114,6 +116,8 @@ pub enum Request { LightClientOptimisticUpdate, // light client finality update request LightClientFinalityUpdate, + // light client updates by range request + LightClientUpdatesByRange(LightClientUpdatesByRangeRequest), /// A request blobs root request. BlobsByRoot(BlobsByRootRequest), /// A request data columns root request. @@ -144,7 +148,8 @@ impl std::convert::From for OutboundRequest { }, Request::LightClientBootstrap(_) | Request::LightClientOptimisticUpdate - | Request::LightClientFinalityUpdate => { + | Request::LightClientFinalityUpdate + | Request::LightClientUpdatesByRange(_) => { unreachable!("Lighthouse never makes an outbound light client request") } Request::BlobsByRange(r) => OutboundRequest::BlobsByRange(r), diff --git a/beacon_node/lighthouse_network/src/service/mod.rs b/beacon_node/lighthouse_network/src/service/mod.rs index 963f4e102a3..d0a16cf5c77 100644 --- a/beacon_node/lighthouse_network/src/service/mod.rs +++ b/beacon_node/lighthouse_network/src/service/mod.rs @@ -1208,6 +1208,10 @@ impl Network { &metrics::TOTAL_RPC_REQUESTS, &["light_client_finality_update"], ), + Request::LightClientUpdatesByRange(_) => metrics::inc_counter_vec( + &metrics::TOTAL_RPC_REQUESTS, + &["light_client_updates_by_range"], + ), Request::BlocksByRange { .. } => { metrics::inc_counter_vec(&metrics::TOTAL_RPC_REQUESTS, &["blocks_by_range"]) } @@ -1585,6 +1589,14 @@ impl Network { ); Some(event) } + InboundRequest::LightClientUpdatesByRange(req) => { + let event = self.build_request( + peer_request_id, + peer_id, + Request::LightClientUpdatesByRange(req), + ); + Some(event) + } } } HandlerEvent::Ok(RPCReceived::Response(id, resp)) => { diff --git a/beacon_node/network/src/network_beacon_processor/mod.rs b/beacon_node/network/src/network_beacon_processor/mod.rs index 7f551c544c7..d5b3e001db5 100644 --- a/beacon_node/network/src/network_beacon_processor/mod.rs +++ b/beacon_node/network/src/network_beacon_processor/mod.rs @@ -11,6 +11,7 @@ use beacon_processor::{ }; use lighthouse_network::rpc::methods::{ BlobsByRangeRequest, BlobsByRootRequest, DataColumnsByRangeRequest, DataColumnsByRootRequest, + LightClientUpdatesByRangeRequest, }; use lighthouse_network::{ rpc::{BlocksByRangeRequest, BlocksByRootRequest, LightClientBootstrapRequest, StatusMessage}, @@ -748,6 +749,23 @@ impl NetworkBeaconProcessor { }) } + /// Create a new work event to process a `LightClientUpdatesByRange` request from the RPC network. + pub fn send_light_client_updates_by_range_request( + self: &Arc, + peer_id: PeerId, + request_id: PeerRequestId, + request: LightClientUpdatesByRangeRequest, + ) -> Result<(), Error> { + let processor = self.clone(); + let process_fn = + move || processor.handle_light_client_updates_by_range(peer_id, request_id, request); + + self.try_send(BeaconWorkEvent { + drop_during_sync: true, + work: Work::LightClientUpdatesByRangeRequest(Box::new(process_fn)), + }) + } + /// Send a message to `sync_tx`. /// /// Creates a log if there is an internal error. diff --git a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs index ddfe6c623ed..ca443bd3128 100644 --- a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs @@ -9,7 +9,7 @@ use lighthouse_network::rpc::methods::{ }; use lighthouse_network::rpc::*; use lighthouse_network::{PeerId, PeerRequestId, ReportSource, Response, SyncInfo}; -use methods::LightClientUpdatesByRangeRequest; +use methods::{LightClientUpdatesByRangeRequest, MAX_REQUEST_LIGHT_CLIENT_UPDATES}; use slog::{debug, error, warn}; use slot_clock::SlotClock; use std::collections::{hash_map::Entry, HashMap}; @@ -381,7 +381,7 @@ impl NetworkBeaconProcessor { Ok(()) } - pub async fn handle_light_client_updates_by_range( + pub fn handle_light_client_updates_by_range( self: &Arc, peer_id: PeerId, request_id: PeerRequestId, @@ -391,14 +391,13 @@ impl NetworkBeaconProcessor { peer_id, request_id, self.clone() - .handle_light_client_updates_by_range_request_inner(peer_id, request_id, request) - .await, - Response::BlocksByRange, + .handle_light_client_updates_by_range_request_inner(peer_id, request_id, request), + Response::LightClientUpdatesByRange, ); } /// Handle a `LightClientUpdatesByRange` request from the peer. - pub async fn handle_light_client_updates_by_range_request_inner( + pub fn handle_light_client_updates_by_range_request_inner( self: Arc, peer_id: PeerId, request_id: PeerRequestId, @@ -410,9 +409,8 @@ impl NetworkBeaconProcessor { "start_period" => req.start_period, ); - // TODO(lc-update) use correct val here // Should not send more than max light client updates - let max_request_size: u64 = 1; + let max_request_size: u64 = MAX_REQUEST_LIGHT_CLIENT_UPDATES; if req.count > max_request_size { return Err(( RPCResponseErrorCode::InvalidRequest, @@ -435,13 +433,13 @@ impl NetworkBeaconProcessor { } }; - lc_updates.iter().for_each(|lc_update| { + for lc_update in lc_updates.iter() { self.send_network_message(NetworkMessage::SendResponse { peer_id, response: Response::LightClientUpdatesByRange(Some(Arc::new(lc_update.clone()))), id: request_id, }); - }); + } let lc_updates_sent = lc_updates.len(); @@ -450,7 +448,7 @@ impl NetworkBeaconProcessor { self.log, "LightClientUpdatesByRange outgoing response processed"; "peer" => %peer_id, - "msg" => "Failed to return all requested light client updates", + "msg" => "Failed to return all requested light client updates. The peer may have requested data ahead of whats currently available.", "start_period" => req.start_period, "requested" => req.count, "returned" => lc_updates_sent diff --git a/beacon_node/network/src/router.rs b/beacon_node/network/src/router.rs index 6d168f2eb09..d9a6ed54f26 100644 --- a/beacon_node/network/src/router.rs +++ b/beacon_node/network/src/router.rs @@ -236,6 +236,11 @@ impl Router { self.network_beacon_processor .send_light_client_finality_update_request(peer_id, request_id), ), + Request::LightClientUpdatesByRange(request) => self + .handle_beacon_processor_send_result( + self.network_beacon_processor + .send_light_client_updates_by_range_request(peer_id, request_id, request), + ), } } diff --git a/consensus/types/src/light_client_update.rs b/consensus/types/src/light_client_update.rs index f7a4e268d77..34f6c34437a 100644 --- a/consensus/types/src/light_client_update.rs +++ b/consensus/types/src/light_client_update.rs @@ -405,7 +405,8 @@ impl LightClientUpdate { true } - // TODO(lc-update) does this math look correct? + // A `LightClientUpdate` has two `LightClientHeader`s + // Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientupdate #[allow(clippy::arithmetic_side_effects)] pub fn ssz_max_len_for_fork(fork_name: ForkName) -> usize { let fixed_len = match fork_name { From 59286323226c11154bebcc011545015d23c60d5e Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Thu, 10 Oct 2024 18:47:12 -0700 Subject: [PATCH 3/6] move max light client updates to eth spec --- beacon_node/lighthouse_network/src/rpc/methods.rs | 2 +- consensus/types/src/eth_spec.rs | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index f2f78ad6bb0..1c1733ece18 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -493,7 +493,7 @@ pub struct LightClientUpdatesByRangeRequest { impl LightClientUpdatesByRangeRequest { pub fn max_requested(&self) -> u64 { - MAX_REQUEST_LIGHT_CLIENT_UPDATES + E::max_light_client_updates_by_range_requests() as u64 } pub fn ssz_min_len() -> usize { diff --git a/consensus/types/src/eth_spec.rs b/consensus/types/src/eth_spec.rs index 09ef8e3c1a7..b2eef0ce674 100644 --- a/consensus/types/src/eth_spec.rs +++ b/consensus/types/src/eth_spec.rs @@ -92,6 +92,7 @@ pub trait EthSpec: type SyncCommitteeSize: Unsigned + Clone + Sync + Send + Debug + PartialEq; /// The number of `sync_committee` subnets. type SyncCommitteeSubnetCount: Unsigned + Clone + Sync + Send + Debug + PartialEq; + type MaxLightClientUpdates: Unsigned + Clone + Sync + Send + Debug + PartialEq; /* * New in Bellatrix */ @@ -374,6 +375,10 @@ pub trait EthSpec: fn kzg_commitments_inclusion_proof_depth() -> usize { Self::KzgCommitmentsInclusionProofDepth::to_usize() } + + fn max_light_client_updates_by_range_requests() -> usize { + Self::MaxLightClientUpdates::to_usize() + } } /// Macro to inherit some type values from another EthSpec. @@ -438,6 +443,7 @@ impl EthSpec for MainnetEthSpec { type MaxAttesterSlashingsElectra = U1; type MaxAttestationsElectra = U8; type MaxWithdrawalRequestsPerPayload = U16; + type MaxLightClientUpdates = U128; fn default_spec() -> ChainSpec { ChainSpec::mainnet() @@ -477,6 +483,7 @@ impl EthSpec for MinimalEthSpec { type FieldElementsPerExtBlob = U8192; type BytesPerCell = U2048; type KzgCommitmentsInclusionProofDepth = U4; + type MaxLightClientUpdates = U128; params_from_eth_spec!(MainnetEthSpec { JustificationBitsLength, @@ -569,6 +576,7 @@ impl EthSpec for GnosisEthSpec { type FieldElementsPerExtBlob = U8192; type BytesPerCell = U2048; type KzgCommitmentsInclusionProofDepth = U4; + type MaxLightClientUpdates = U128; fn default_spec() -> ChainSpec { ChainSpec::gnosis() From 0798629118a884469aac3ba5a3fccd46925182fb Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Mon, 14 Oct 2024 09:45:16 -0700 Subject: [PATCH 4/6] remove ethspec dependency --- beacon_node/lighthouse_network/src/rpc/methods.rs | 12 ++++-------- beacon_node/lighthouse_network/src/rpc/protocol.rs | 2 +- .../src/network_beacon_processor/rpc_methods.rs | 4 ++-- consensus/types/src/eth_spec.rs | 8 -------- consensus/types/src/light_client_update.rs | 4 ++++ 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index 1c1733ece18..38d0e0133dd 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -14,21 +14,17 @@ use std::sync::Arc; use strum::IntoStaticStr; use superstruct::superstruct; use types::blob_sidecar::BlobIdentifier; -use types::LightClientUpdate; +use types::light_client_update::MAX_REQUEST_LIGHT_CLIENT_UPDATES; use types::{ blob_sidecar::BlobSidecar, ChainSpec, ColumnIndex, DataColumnIdentifier, DataColumnSidecar, Epoch, EthSpec, Hash256, LightClientBootstrap, LightClientFinalityUpdate, - LightClientOptimisticUpdate, RuntimeVariableList, SignedBeaconBlock, Slot, + LightClientOptimisticUpdate, LightClientUpdate, RuntimeVariableList, SignedBeaconBlock, Slot, }; /// Maximum length of error message. pub type MaxErrorLen = U256; pub const MAX_ERROR_LEN: u64 = 256; -// Max light client updates by range request limits -// spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#configuration -pub const MAX_REQUEST_LIGHT_CLIENT_UPDATES: u64 = 128; - /// Wrapper over SSZ List to represent error message in rpc responses. #[derive(Debug, Clone)] pub struct ErrorType(pub VariableList); @@ -492,8 +488,8 @@ pub struct LightClientUpdatesByRangeRequest { } impl LightClientUpdatesByRangeRequest { - pub fn max_requested(&self) -> u64 { - E::max_light_client_updates_by_range_requests() as u64 + pub fn max_requested(&self) -> u64 { + MAX_REQUEST_LIGHT_CLIENT_UPDATES } pub fn ssz_min_len() -> usize { diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index d7308ca0653..16c3a133912 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -791,7 +791,7 @@ impl RequestType { RequestType::LightClientBootstrap(_) => 1, RequestType::LightClientOptimisticUpdate => 1, RequestType::LightClientFinalityUpdate => 1, - RequestType::LightClientUpdatesByRange(_) => MAX_REQUEST_LIGHT_CLIENT_UPDATES, + RequestType::LightClientUpdatesByRange(req) => req.max_requested(), } } diff --git a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs index fefabc05fa8..310901f7325 100644 --- a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs @@ -10,7 +10,7 @@ use lighthouse_network::rpc::methods::{ }; use lighthouse_network::rpc::*; use lighthouse_network::{PeerId, PeerRequestId, ReportSource, Response, SyncInfo}; -use methods::{LightClientUpdatesByRangeRequest, MAX_REQUEST_LIGHT_CLIENT_UPDATES}; +use methods::LightClientUpdatesByRangeRequest; use slog::{debug, error, warn}; use slot_clock::SlotClock; use std::collections::{hash_map::Entry, HashMap}; @@ -470,7 +470,7 @@ impl NetworkBeaconProcessor { ); // Should not send more than max light client updates - let max_request_size: u64 = MAX_REQUEST_LIGHT_CLIENT_UPDATES; + let max_request_size: u64 = req.max_requested(); if req.count > max_request_size { return Err(( RpcErrorResponse::InvalidRequest, diff --git a/consensus/types/src/eth_spec.rs b/consensus/types/src/eth_spec.rs index b2eef0ce674..09ef8e3c1a7 100644 --- a/consensus/types/src/eth_spec.rs +++ b/consensus/types/src/eth_spec.rs @@ -92,7 +92,6 @@ pub trait EthSpec: type SyncCommitteeSize: Unsigned + Clone + Sync + Send + Debug + PartialEq; /// The number of `sync_committee` subnets. type SyncCommitteeSubnetCount: Unsigned + Clone + Sync + Send + Debug + PartialEq; - type MaxLightClientUpdates: Unsigned + Clone + Sync + Send + Debug + PartialEq; /* * New in Bellatrix */ @@ -375,10 +374,6 @@ pub trait EthSpec: fn kzg_commitments_inclusion_proof_depth() -> usize { Self::KzgCommitmentsInclusionProofDepth::to_usize() } - - fn max_light_client_updates_by_range_requests() -> usize { - Self::MaxLightClientUpdates::to_usize() - } } /// Macro to inherit some type values from another EthSpec. @@ -443,7 +438,6 @@ impl EthSpec for MainnetEthSpec { type MaxAttesterSlashingsElectra = U1; type MaxAttestationsElectra = U8; type MaxWithdrawalRequestsPerPayload = U16; - type MaxLightClientUpdates = U128; fn default_spec() -> ChainSpec { ChainSpec::mainnet() @@ -483,7 +477,6 @@ impl EthSpec for MinimalEthSpec { type FieldElementsPerExtBlob = U8192; type BytesPerCell = U2048; type KzgCommitmentsInclusionProofDepth = U4; - type MaxLightClientUpdates = U128; params_from_eth_spec!(MainnetEthSpec { JustificationBitsLength, @@ -576,7 +569,6 @@ impl EthSpec for GnosisEthSpec { type FieldElementsPerExtBlob = U8192; type BytesPerCell = U2048; type KzgCommitmentsInclusionProofDepth = U4; - type MaxLightClientUpdates = U128; fn default_spec() -> ChainSpec { ChainSpec::gnosis() diff --git a/consensus/types/src/light_client_update.rs b/consensus/types/src/light_client_update.rs index 34f6c34437a..1f5592a929f 100644 --- a/consensus/types/src/light_client_update.rs +++ b/consensus/types/src/light_client_update.rs @@ -36,6 +36,10 @@ pub const CURRENT_SYNC_COMMITTEE_PROOF_LEN: usize = 5; pub const NEXT_SYNC_COMMITTEE_PROOF_LEN: usize = 5; pub const EXECUTION_PAYLOAD_PROOF_LEN: usize = 4; +// Max light client updates by range request limits +// spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#configuration +pub const MAX_REQUEST_LIGHT_CLIENT_UPDATES: u64 = 128; + type FinalityBranch = FixedVector; type NextSyncCommitteeBranch = FixedVector; From 8898d07190dec1975295fdd3190df5c3293b2a75 Mon Sep 17 00:00:00 2001 From: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:12:15 +0300 Subject: [PATCH 5/6] Update beacon_node/network/src/network_beacon_processor/rpc_methods.rs Co-authored-by: Michael Sproul --- beacon_node/network/src/network_beacon_processor/rpc_methods.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs index 310901f7325..6d32806713d 100644 --- a/beacon_node/network/src/network_beacon_processor/rpc_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/rpc_methods.rs @@ -509,7 +509,7 @@ impl NetworkBeaconProcessor { self.log, "LightClientUpdatesByRange outgoing response processed"; "peer" => %peer_id, - "msg" => "Failed to return all requested light client updates. The peer may have requested data ahead of whats currently available.", + "info" => "Failed to return all requested light client updates. The peer may have requested data ahead of whats currently available", "start_period" => req.start_period, "requested" => req.count, "returned" => lc_updates_sent From 48cd406e4a6d07739f692fa2598a4e4451732726 Mon Sep 17 00:00:00 2001 From: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:13:12 +0300 Subject: [PATCH 6/6] Update beacon_node/lighthouse_network/src/rpc/methods.rs Co-authored-by: Michael Sproul --- beacon_node/lighthouse_network/src/rpc/methods.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/beacon_node/lighthouse_network/src/rpc/methods.rs b/beacon_node/lighthouse_network/src/rpc/methods.rs index 38d0e0133dd..bb8bfb0e206 100644 --- a/beacon_node/lighthouse_network/src/rpc/methods.rs +++ b/beacon_node/lighthouse_network/src/rpc/methods.rs @@ -502,12 +502,7 @@ impl LightClientUpdatesByRangeRequest { } pub fn ssz_max_len() -> usize { - LightClientUpdatesByRangeRequest { - start_period: 0, - count: 0, - } - .as_ssz_bytes() - .len() + Self::ssz_min_len() } }