Skip to content

Commit

Permalink
Support LightClientFinalityUpdate and LightClientOptimisticUpdate
Browse files Browse the repository at this point in the history
… rpcs (#3849)

* add light client optimistic and finality update rpc

* Arc the updates in the response

* add conditional advertisement for both LightClientOptimisticUpdate and LightClientFinalityUpdate

* alter display for inboundrequest light client optimistic and finality updates

* remove LightClientOptimistic/FinalityReuest struct and some minor fixes

* rebase

* failing rpc_test for LightClientBootstrap and beginning of MockLib2pLightClient

* minor change

* added MockRPCHandler by importing everything except OutboundRequest. Need to implement the ConnectionHandler trait now should be copy pastable

* almost there but ran into issue where needed to implement BaseOutboundRequest.

* failing but running with a light client service of sorts

* small test change

* changed Protocol::LightClientBootstrap response limit

* deleted some stuff from ConnectionHandler Implementation for the mock light client if you need to make something with multiple requests work maybe check here

* deleted purging expired inbound/outbound streams code

* deleted drive inbound streams that need to be processed

* removed unused imports

* made things private again

* deleted inject_fully_negotiated_inbound

* made more things private again

* more

* turned the logger off in the test

* added failing test for new rpc

* add rate limit for new rpcs

* change InboundUpgrade function to use new rpcs. fmt. add test for LightClientFinalityUpdate

* rebasing fix

* add LightClientUpdate to handle_rpc functions

* added context bytes

* fmt

* use correct unsed_tcp4_port function

* fix for recent config changes and adding context_bytes for the light client protocols

* fix clippy complaint

* Merge branch 'unstable' into lc-reqresp

# Conflicts:
#	beacon_node/beacon_processor/src/lib.rs
#	beacon_node/lighthouse_network/src/peer_manager/mod.rs
#	beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
#	beacon_node/lighthouse_network/src/rpc/config.rs
#	beacon_node/lighthouse_network/src/rpc/methods.rs
#	beacon_node/lighthouse_network/src/rpc/mod.rs
#	beacon_node/lighthouse_network/src/rpc/outbound.rs
#	beacon_node/lighthouse_network/src/rpc/protocol.rs
#	beacon_node/lighthouse_network/src/rpc/rate_limiter.rs
#	beacon_node/lighthouse_network/src/rpc/self_limiter.rs
#	beacon_node/lighthouse_network/src/service/api_types.rs
#	beacon_node/lighthouse_network/tests/common/mod.rs
#	beacon_node/lighthouse_network/tests/rpc_tests.rs
#	beacon_node/network/src/network_beacon_processor/rpc_methods.rs
#	beacon_node/network/src/router.rs

* Error handling updates and various cleanups.

* Moar minor clean ups.

* Do not ban peer for rate limiting light client requests

* Merge branch 'unstable' into lc-reqresp. Also removed the mock light client tests to make it compile (See #4940).

# Conflicts:
#	beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
#	beacon_node/lighthouse_network/src/rpc/methods.rs
#	beacon_node/lighthouse_network/src/rpc/mod.rs
#	beacon_node/lighthouse_network/src/rpc/protocol.rs
#	beacon_node/lighthouse_network/src/service/api_types.rs
#	beacon_node/lighthouse_network/tests/common/mod.rs
#	beacon_node/network/src/network_beacon_processor/rpc_methods.rs
#	beacon_node/network/src/router.rs
#	consensus/types/src/light_client_bootstrap.rs
#	consensus/types/src/light_client_finality_update.rs
#	consensus/types/src/light_client_optimistic_update.rs

* Remove unnecessary changes

* Add missing light client queue handling.

* Merge branch 'unstable' into lc-reqresp

* Merge branch 'unstable' into lc-reqresp

# Conflicts:
#	beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
#	beacon_node/lighthouse_network/src/service/api_types.rs
#	consensus/types/src/light_client_finality_update.rs
#	consensus/types/src/light_client_optimistic_update.rs

* Add context bytes for light client RPC responses.

* Add RPC limits for light client object.

* Fix lint

* Fix incorrect light client max size computation.

* Merge branch 'unstable' into lc-reqresp

# Conflicts:
#	beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
#	beacon_node/lighthouse_network/src/rpc/protocol.rs
#	beacon_node/lighthouse_network/src/service/api_types.rs

* Remove unwanted local changes.

* Merge branch 'unstable' into lc-reqresp

* Replace `unimplemented` electra code path with deneb values.
  • Loading branch information
GeemoCandama authored Apr 9, 2024
1 parent 1b88d29 commit 32be063
Show file tree
Hide file tree
Showing 19 changed files with 612 additions and 70 deletions.
41 changes: 36 additions & 5 deletions beacon_node/beacon_processor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ const MAX_BLS_TO_EXECUTION_CHANGE_QUEUE_LEN: usize = 16_384;
/// will be stored before we start dropping them.
const MAX_LIGHT_CLIENT_BOOTSTRAP_QUEUE_LEN: usize = 1_024;

/// The maximum number of queued `LightClientOptimisticUpdateRequest` objects received from the network RPC that
/// will be stored before we start dropping them.
const MAX_LIGHT_CLIENT_OPTIMISTIC_UPDATE_QUEUE_LEN: usize = 512;

/// The maximum number of queued `LightClientFinalityUpdateRequest` objects received from the network RPC that
/// will be stored before we start dropping them.
const MAX_LIGHT_CLIENT_FINALITY_UPDATE_QUEUE_LEN: usize = 512;

/// The maximum number of priority-0 (highest priority) messages that will be queued before
/// they begin to be dropped.
const MAX_API_REQUEST_P0_QUEUE_LEN: usize = 1_024;
Expand Down Expand Up @@ -243,6 +251,8 @@ pub const BLOCKS_BY_ROOTS_REQUEST: &str = "blocks_by_roots_request";
pub const BLOBS_BY_RANGE_REQUEST: &str = "blobs_by_range_request";
pub const BLOBS_BY_ROOTS_REQUEST: &str = "blobs_by_roots_request";
pub const LIGHT_CLIENT_BOOTSTRAP_REQUEST: &str = "light_client_bootstrap";
pub const LIGHT_CLIENT_FINALITY_UPDATE_REQUEST: &str = "light_client_finality_update_request";
pub const LIGHT_CLIENT_OPTIMISTIC_UPDATE_REQUEST: &str = "light_client_optimistic_update_request";
pub const UNKNOWN_BLOCK_ATTESTATION: &str = "unknown_block_attestation";
pub const UNKNOWN_BLOCK_AGGREGATE: &str = "unknown_block_aggregate";
pub const UNKNOWN_LIGHT_CLIENT_UPDATE: &str = "unknown_light_client_update";
Expand Down Expand Up @@ -620,6 +630,8 @@ pub enum Work<E: EthSpec> {
BlobsByRootsRequest(BlockingFn),
GossipBlsToExecutionChange(BlockingFn),
LightClientBootstrapRequest(BlockingFn),
LightClientOptimisticUpdateRequest(BlockingFn),
LightClientFinalityUpdateRequest(BlockingFn),
ApiRequestP0(BlockingOrAsync),
ApiRequestP1(BlockingOrAsync),
}
Expand Down Expand Up @@ -659,6 +671,8 @@ impl<E: EthSpec> Work<E> {
Work::BlobsByRangeRequest(_) => BLOBS_BY_RANGE_REQUEST,
Work::BlobsByRootsRequest(_) => BLOBS_BY_ROOTS_REQUEST,
Work::LightClientBootstrapRequest(_) => LIGHT_CLIENT_BOOTSTRAP_REQUEST,
Work::LightClientOptimisticUpdateRequest(_) => LIGHT_CLIENT_OPTIMISTIC_UPDATE_REQUEST,
Work::LightClientFinalityUpdateRequest(_) => LIGHT_CLIENT_FINALITY_UPDATE_REQUEST,
Work::UnknownBlockAttestation { .. } => UNKNOWN_BLOCK_ATTESTATION,
Work::UnknownBlockAggregate { .. } => UNKNOWN_BLOCK_AGGREGATE,
Work::GossipBlsToExecutionChange(_) => GOSSIP_BLS_TO_EXECUTION_CHANGE,
Expand Down Expand Up @@ -820,7 +834,11 @@ impl<E: EthSpec> BeaconProcessor<E> {
let mut gossip_bls_to_execution_change_queue =
FifoQueue::new(MAX_BLS_TO_EXECUTION_CHANGE_QUEUE_LEN);

let mut lcbootstrap_queue = FifoQueue::new(MAX_LIGHT_CLIENT_BOOTSTRAP_QUEUE_LEN);
let mut lc_bootstrap_queue = FifoQueue::new(MAX_LIGHT_CLIENT_BOOTSTRAP_QUEUE_LEN);
let mut lc_optimistic_update_queue =
FifoQueue::new(MAX_LIGHT_CLIENT_OPTIMISTIC_UPDATE_QUEUE_LEN);
let mut lc_finality_update_queue =
FifoQueue::new(MAX_LIGHT_CLIENT_FINALITY_UPDATE_QUEUE_LEN);

let mut api_request_p0_queue = FifoQueue::new(MAX_API_REQUEST_P0_QUEUE_LEN);
let mut api_request_p1_queue = FifoQueue::new(MAX_API_REQUEST_P1_QUEUE_LEN);
Expand Down Expand Up @@ -1137,9 +1155,14 @@ impl<E: EthSpec> BeaconProcessor<E> {
// Handle backfill sync chain segments.
} else if let Some(item) = backfill_chain_segment.pop() {
self.spawn_worker(item, idle_tx);
// This statement should always be the final else statement.
} else if let Some(item) = lcbootstrap_queue.pop() {
// Handle light client requests.
} else if let Some(item) = lc_bootstrap_queue.pop() {
self.spawn_worker(item, idle_tx);
} else if let Some(item) = lc_optimistic_update_queue.pop() {
self.spawn_worker(item, idle_tx);
} else if let Some(item) = lc_finality_update_queue.pop() {
self.spawn_worker(item, idle_tx);
// This statement should always be the final else statement.
} else {
// Let the journal know that a worker is freed and there's nothing else
// for it to do.
Expand Down Expand Up @@ -1249,7 +1272,13 @@ impl<E: EthSpec> BeaconProcessor<E> {
blbrange_queue.push(work, work_id, &self.log)
}
Work::LightClientBootstrapRequest { .. } => {
lcbootstrap_queue.push(work, work_id, &self.log)
lc_bootstrap_queue.push(work, work_id, &self.log)
}
Work::LightClientOptimisticUpdateRequest { .. } => {
lc_optimistic_update_queue.push(work, work_id, &self.log)
}
Work::LightClientFinalityUpdateRequest { .. } => {
lc_finality_update_queue.push(work, work_id, &self.log)
}
Work::UnknownBlockAttestation { .. } => {
unknown_block_attestation_queue.push(work)
Expand Down Expand Up @@ -1480,7 +1509,9 @@ impl<E: EthSpec> BeaconProcessor<E> {
| Work::GossipLightClientOptimisticUpdate(process_fn)
| Work::Status(process_fn)
| Work::GossipBlsToExecutionChange(process_fn)
| Work::LightClientBootstrapRequest(process_fn) => {
| Work::LightClientBootstrapRequest(process_fn)
| Work::LightClientOptimisticUpdateRequest(process_fn)
| Work::LightClientFinalityUpdateRequest(process_fn) => {
task_spawner.spawn_blocking(process_fn)
}
};
Expand Down
10 changes: 9 additions & 1 deletion beacon_node/lighthouse_network/src/peer_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,11 @@ impl<E: EthSpec> PeerManager<E> {
Protocol::BlocksByRange => PeerAction::MidToleranceError,
Protocol::BlocksByRoot => PeerAction::MidToleranceError,
Protocol::BlobsByRange => PeerAction::MidToleranceError,
Protocol::LightClientBootstrap => PeerAction::LowToleranceError,
// 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::BlobsByRoot => PeerAction::MidToleranceError,
Protocol::Goodbye => PeerAction::LowToleranceError,
Protocol::MetaData => PeerAction::LowToleranceError,
Expand All @@ -575,6 +579,8 @@ impl<E: EthSpec> PeerManager<E> {
Protocol::BlobsByRoot => return,
Protocol::Goodbye => return,
Protocol::LightClientBootstrap => return,
Protocol::LightClientOptimisticUpdate => return,
Protocol::LightClientFinalityUpdate => return,
Protocol::MetaData => PeerAction::Fatal,
Protocol::Status => PeerAction::Fatal,
}
Expand All @@ -592,6 +598,8 @@ impl<E: EthSpec> PeerManager<E> {
Protocol::BlobsByRange => PeerAction::MidToleranceError,
Protocol::BlobsByRoot => PeerAction::MidToleranceError,
Protocol::LightClientBootstrap => return,
Protocol::LightClientOptimisticUpdate => return,
Protocol::LightClientFinalityUpdate => return,
Protocol::Goodbye => return,
Protocol::MetaData => return,
Protocol::Status => return,
Expand Down
112 changes: 81 additions & 31 deletions beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ use std::io::{Read, Write};
use std::marker::PhantomData;
use std::sync::Arc;
use tokio_util::codec::{Decoder, Encoder};
use types::ChainSpec;
use types::{
BlobSidecar, EthSpec, ForkContext, ForkName, Hash256, LightClientBootstrap,
RuntimeVariableList, SignedBeaconBlock, SignedBeaconBlockAltair, SignedBeaconBlockBase,
SignedBeaconBlockCapella, SignedBeaconBlockDeneb, SignedBeaconBlockElectra,
SignedBeaconBlockMerge,
BlobSidecar, ChainSpec, EthSpec, ForkContext, ForkName, Hash256, LightClientBootstrap,
LightClientFinalityUpdate, LightClientOptimisticUpdate, RuntimeVariableList, SignedBeaconBlock,
SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockCapella,
SignedBeaconBlockDeneb, SignedBeaconBlockElectra, SignedBeaconBlockMerge,
};
use unsigned_varint::codec::Uvi;

Expand Down Expand Up @@ -72,6 +71,8 @@ impl<E: EthSpec> Encoder<RPCCodedResponse<E>> for SSZSnappyInboundCodec<E> {
RPCResponse::BlobsByRange(res) => res.as_ssz_bytes(),
RPCResponse::BlobsByRoot(res) => res.as_ssz_bytes(),
RPCResponse::LightClientBootstrap(res) => res.as_ssz_bytes(),
RPCResponse::LightClientOptimisticUpdate(res) => res.as_ssz_bytes(),
RPCResponse::LightClientFinalityUpdate(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.
Expand Down Expand Up @@ -387,32 +388,51 @@ fn context_bytes<E: EthSpec>(
// Add the context bytes if required
if protocol.has_context_bytes() {
if let RPCCodedResponse::Success(rpc_variant) = resp {
if let RPCResponse::BlocksByRange(ref_box_block)
| RPCResponse::BlocksByRoot(ref_box_block) = rpc_variant
{
return match **ref_box_block {
// NOTE: If you are adding another fork type here, be sure to modify the
// `fork_context.to_context_bytes()` function to support it as well!
SignedBeaconBlock::Electra { .. } => {
fork_context.to_context_bytes(ForkName::Electra)
}
SignedBeaconBlock::Deneb { .. } => {
fork_context.to_context_bytes(ForkName::Deneb)
}
SignedBeaconBlock::Capella { .. } => {
fork_context.to_context_bytes(ForkName::Capella)
}
SignedBeaconBlock::Merge { .. } => {
fork_context.to_context_bytes(ForkName::Merge)
}
SignedBeaconBlock::Altair { .. } => {
fork_context.to_context_bytes(ForkName::Altair)
}
SignedBeaconBlock::Base { .. } => Some(fork_context.genesis_context_bytes()),
};
}
if let RPCResponse::BlobsByRange(_) | RPCResponse::BlobsByRoot(_) = rpc_variant {
return fork_context.to_context_bytes(ForkName::Deneb);
match rpc_variant {
RPCResponse::BlocksByRange(ref_box_block)
| RPCResponse::BlocksByRoot(ref_box_block) => {
return match **ref_box_block {
// NOTE: If you are adding another fork type here, be sure to modify the
// `fork_context.to_context_bytes()` function to support it as well!
SignedBeaconBlock::Electra { .. } => {
fork_context.to_context_bytes(ForkName::Electra)
}
SignedBeaconBlock::Deneb { .. } => {
fork_context.to_context_bytes(ForkName::Deneb)
}
SignedBeaconBlock::Capella { .. } => {
fork_context.to_context_bytes(ForkName::Capella)
}
SignedBeaconBlock::Merge { .. } => {
fork_context.to_context_bytes(ForkName::Merge)
}
SignedBeaconBlock::Altair { .. } => {
fork_context.to_context_bytes(ForkName::Altair)
}
SignedBeaconBlock::Base { .. } => {
Some(fork_context.genesis_context_bytes())
}
};
}
RPCResponse::BlobsByRange(_) | RPCResponse::BlobsByRoot(_) => {
return fork_context.to_context_bytes(ForkName::Deneb);
}
RPCResponse::LightClientBootstrap(lc_bootstrap) => {
return lc_bootstrap
.map_with_fork_name(|fork_name| fork_context.to_context_bytes(fork_name));
}
RPCResponse::LightClientOptimisticUpdate(lc_optimistic_update) => {
return lc_optimistic_update
.map_with_fork_name(|fork_name| fork_context.to_context_bytes(fork_name));
}
RPCResponse::LightClientFinalityUpdate(lc_finality_update) => {
return lc_finality_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;
}
}
}
}
Expand Down Expand Up @@ -500,6 +520,12 @@ fn handle_rpc_request<E: EthSpec>(
root: Hash256::from_ssz_bytes(decoded_buffer)?,
}),
)),
SupportedProtocol::LightClientOptimisticUpdateV1 => {
Ok(Some(InboundRequest::LightClientOptimisticUpdate))
}
SupportedProtocol::LightClientFinalityUpdateV1 => {
Ok(Some(InboundRequest::LightClientFinalityUpdate))
}
// MetaData requests return early from InboundUpgrade and do not reach the decoder.
// Handle this case just for completeness.
SupportedProtocol::MetaDataV2 => {
Expand Down Expand Up @@ -596,6 +622,30 @@ fn handle_rpc_response<E: EthSpec>(
),
)),
},
SupportedProtocol::LightClientOptimisticUpdateV1 => match fork_name {
Some(fork_name) => Ok(Some(RPCResponse::LightClientOptimisticUpdate(Arc::new(
LightClientOptimisticUpdate::from_ssz_bytes(decoded_buffer, fork_name)?,
)))),
None => Err(RPCError::ErrorResponse(
RPCResponseErrorCode::InvalidRequest,
format!(
"No context bytes provided for {:?} response",
versioned_protocol
),
)),
},
SupportedProtocol::LightClientFinalityUpdateV1 => match fork_name {
Some(fork_name) => Ok(Some(RPCResponse::LightClientFinalityUpdate(Arc::new(
LightClientFinalityUpdate::from_ssz_bytes(decoded_buffer, fork_name)?,
)))),
None => Err(RPCError::ErrorResponse(
RPCResponseErrorCode::InvalidRequest,
format!(
"No context bytes provided for {:?} response",
versioned_protocol
),
)),
},
// MetaData V2 responses have no context bytes, so behave similarly to V1 responses
SupportedProtocol::MetaDataV2 => Ok(Some(RPCResponse::MetaData(MetaData::V2(
MetaDataV2::from_ssz_bytes(decoded_buffer)?,
Expand Down
21 changes: 21 additions & 0 deletions beacon_node/lighthouse_network/src/rpc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ pub struct RateLimiterConfig {
pub(super) blobs_by_range_quota: Quota,
pub(super) blobs_by_root_quota: Quota,
pub(super) light_client_bootstrap_quota: Quota,
pub(super) light_client_optimistic_update_quota: Quota,
pub(super) light_client_finality_update_quota: Quota,
}

impl RateLimiterConfig {
Expand All @@ -104,6 +106,8 @@ impl RateLimiterConfig {
pub const DEFAULT_BLOBS_BY_RANGE_QUOTA: Quota = Quota::n_every(768, 10);
pub const DEFAULT_BLOBS_BY_ROOT_QUOTA: Quota = Quota::n_every(128, 10);
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);
}

impl Default for RateLimiterConfig {
Expand All @@ -118,6 +122,9 @@ impl Default for RateLimiterConfig {
blobs_by_range_quota: Self::DEFAULT_BLOBS_BY_RANGE_QUOTA,
blobs_by_root_quota: Self::DEFAULT_BLOBS_BY_ROOT_QUOTA,
light_client_bootstrap_quota: Self::DEFAULT_LIGHT_CLIENT_BOOTSTRAP_QUOTA,
light_client_optimistic_update_quota:
Self::DEFAULT_LIGHT_CLIENT_OPTIMISTIC_UPDATE_QUOTA,
light_client_finality_update_quota: Self::DEFAULT_LIGHT_CLIENT_FINALITY_UPDATE_QUOTA,
}
}
}
Expand Down Expand Up @@ -164,6 +171,8 @@ impl FromStr for RateLimiterConfig {
let mut blobs_by_range_quota = None;
let mut blobs_by_root_quota = None;
let mut light_client_bootstrap_quota = None;
let mut light_client_optimistic_update_quota = None;
let mut light_client_finality_update_quota = None;

for proto_def in s.split(';') {
let ProtocolQuota { protocol, quota } = proto_def.parse()?;
Expand All @@ -180,6 +189,14 @@ impl FromStr for RateLimiterConfig {
Protocol::LightClientBootstrap => {
light_client_bootstrap_quota = light_client_bootstrap_quota.or(quota)
}
Protocol::LightClientOptimisticUpdate => {
light_client_optimistic_update_quota =
light_client_optimistic_update_quota.or(quota)
}
Protocol::LightClientFinalityUpdate => {
light_client_finality_update_quota =
light_client_finality_update_quota.or(quota)
}
}
}
Ok(RateLimiterConfig {
Expand All @@ -196,6 +213,10 @@ impl FromStr for RateLimiterConfig {
blobs_by_root_quota: blobs_by_root_quota.unwrap_or(Self::DEFAULT_BLOBS_BY_ROOT_QUOTA),
light_client_bootstrap_quota: light_client_bootstrap_quota
.unwrap_or(Self::DEFAULT_LIGHT_CLIENT_BOOTSTRAP_QUOTA),
light_client_optimistic_update_quota: light_client_optimistic_update_quota
.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),
})
}
}
Expand Down
Loading

0 comments on commit 32be063

Please sign in to comment.