Skip to content

Commit d5a2de7

Browse files
Added LightClientBootstrap V1 (#3711)
## Issue Addressed Partially addresses #3651 ## Proposed Changes Adds server-side support for light_client_bootstrap_v1 topic ## Additional Info This PR, creates each time a bootstrap without using cache, I do not know how necessary a cache is in this case as this topic is not supposed to be called frequently and IMHO we can just prevent abuse by using the limiter, but let me know what you think or if there is any caveat to this, or if it is necessary only for the sake of good practice. Co-authored-by: Pawan Dhananjay <[email protected]>
1 parent bf533c8 commit d5a2de7

File tree

17 files changed

+271
-69
lines changed

17 files changed

+271
-69
lines changed

beacon_node/beacon_chain/src/chain_config.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ pub struct ChainConfig {
4747
pub count_unrealized_full: CountUnrealizedFull,
4848
/// Optionally set timeout for calls to checkpoint sync endpoint.
4949
pub checkpoint_sync_url_timeout: u64,
50-
/// Whether to enable the light client server protocol.
51-
pub enable_light_client_server: bool,
5250
}
5351

5452
impl Default for ChainConfig {
@@ -70,7 +68,6 @@ impl Default for ChainConfig {
7068
paranoid_block_proposal: false,
7169
count_unrealized_full: CountUnrealizedFull::default(),
7270
checkpoint_sync_url_timeout: 60,
73-
enable_light_client_server: false,
7471
}
7572
}
7673
}

beacon_node/lighthouse_network/src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ pub struct Config {
130130

131131
/// Whether metrics are enabled.
132132
pub metrics_enabled: bool,
133+
134+
/// Whether light client protocols should be enabled.
135+
pub enable_light_client_server: bool,
133136
}
134137

135138
impl Default for Config {
@@ -207,6 +210,7 @@ impl Default for Config {
207210
shutdown_after_sync: false,
208211
topics: Vec::new(),
209212
metrics_enabled: false,
213+
enable_light_client_server: false,
210214
}
211215
}
212216
}

beacon_node/lighthouse_network/src/peer_manager/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
501501
Protocol::Ping => PeerAction::MidToleranceError,
502502
Protocol::BlocksByRange => PeerAction::MidToleranceError,
503503
Protocol::BlocksByRoot => PeerAction::MidToleranceError,
504+
Protocol::LightClientBootstrap => PeerAction::LowToleranceError,
504505
Protocol::Goodbye => PeerAction::LowToleranceError,
505506
Protocol::MetaData => PeerAction::LowToleranceError,
506507
Protocol::Status => PeerAction::LowToleranceError,
@@ -517,6 +518,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
517518
Protocol::BlocksByRange => return,
518519
Protocol::BlocksByRoot => return,
519520
Protocol::Goodbye => return,
521+
Protocol::LightClientBootstrap => return,
520522
Protocol::MetaData => PeerAction::LowToleranceError,
521523
Protocol::Status => PeerAction::LowToleranceError,
522524
}
@@ -531,6 +533,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
531533
Protocol::Ping => PeerAction::LowToleranceError,
532534
Protocol::BlocksByRange => PeerAction::MidToleranceError,
533535
Protocol::BlocksByRoot => PeerAction::MidToleranceError,
536+
Protocol::LightClientBootstrap => return,
534537
Protocol::Goodbye => return,
535538
Protocol::MetaData => return,
536539
Protocol::Status => return,

beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use std::marker::PhantomData;
1616
use std::sync::Arc;
1717
use tokio_util::codec::{Decoder, Encoder};
1818
use types::{
19-
EthSpec, ForkContext, ForkName, SignedBeaconBlock, SignedBeaconBlockAltair,
20-
SignedBeaconBlockBase, SignedBeaconBlockMerge,
19+
light_client_bootstrap::LightClientBootstrap, EthSpec, ForkContext, ForkName, Hash256,
20+
SignedBeaconBlock, SignedBeaconBlockAltair, SignedBeaconBlockBase, SignedBeaconBlockMerge,
2121
};
2222
use unsigned_varint::codec::Uvi;
2323

@@ -70,6 +70,7 @@ impl<TSpec: EthSpec> Encoder<RPCCodedResponse<TSpec>> for SSZSnappyInboundCodec<
7070
RPCResponse::Status(res) => res.as_ssz_bytes(),
7171
RPCResponse::BlocksByRange(res) => res.as_ssz_bytes(),
7272
RPCResponse::BlocksByRoot(res) => res.as_ssz_bytes(),
73+
RPCResponse::LightClientBootstrap(res) => res.as_ssz_bytes(),
7374
RPCResponse::Pong(res) => res.data.as_ssz_bytes(),
7475
RPCResponse::MetaData(res) =>
7576
// Encode the correct version of the MetaData response based on the negotiated version.
@@ -230,6 +231,7 @@ impl<TSpec: EthSpec> Encoder<OutboundRequest<TSpec>> for SSZSnappyOutboundCodec<
230231
OutboundRequest::BlocksByRoot(req) => req.block_roots.as_ssz_bytes(),
231232
OutboundRequest::Ping(req) => req.as_ssz_bytes(),
232233
OutboundRequest::MetaData(_) => return Ok(()), // no metadata to encode
234+
OutboundRequest::LightClientBootstrap(req) => req.as_ssz_bytes(),
233235
};
234236
// SSZ encoded bytes should be within `max_packet_size`
235237
if bytes.len() > self.max_packet_size {
@@ -472,7 +474,11 @@ fn handle_v1_request<T: EthSpec>(
472474
Protocol::Ping => Ok(Some(InboundRequest::Ping(Ping {
473475
data: u64::from_ssz_bytes(decoded_buffer)?,
474476
}))),
475-
477+
Protocol::LightClientBootstrap => Ok(Some(InboundRequest::LightClientBootstrap(
478+
LightClientBootstrapRequest {
479+
root: Hash256::from_ssz_bytes(decoded_buffer)?,
480+
},
481+
))),
476482
// MetaData requests return early from InboundUpgrade and do not reach the decoder.
477483
// Handle this case just for completeness.
478484
Protocol::MetaData => {
@@ -544,6 +550,9 @@ fn handle_v1_response<T: EthSpec>(
544550
Protocol::MetaData => Ok(Some(RPCResponse::MetaData(MetaData::V1(
545551
MetaDataV1::from_ssz_bytes(decoded_buffer)?,
546552
)))),
553+
Protocol::LightClientBootstrap => Ok(Some(RPCResponse::LightClientBootstrap(
554+
LightClientBootstrap::from_ssz_bytes(decoded_buffer)?,
555+
))),
547556
}
548557
}
549558

@@ -867,6 +876,9 @@ mod tests {
867876
OutboundRequest::MetaData(metadata) => {
868877
assert_eq!(decoded, InboundRequest::MetaData(metadata))
869878
}
879+
OutboundRequest::LightClientBootstrap(bootstrap) => {
880+
assert_eq!(decoded, InboundRequest::LightClientBootstrap(bootstrap))
881+
}
870882
}
871883
}
872884
}

beacon_node/lighthouse_network/src/rpc/methods.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ use std::ops::Deref;
1212
use std::sync::Arc;
1313
use strum::IntoStaticStr;
1414
use superstruct::superstruct;
15-
use types::{Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot};
15+
use types::{
16+
light_client_bootstrap::LightClientBootstrap, Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot,
17+
};
1618

1719
/// Maximum number of blocks in a single request.
1820
pub type MaxRequestBlocks = U1024;
@@ -243,6 +245,9 @@ pub enum RPCResponse<T: EthSpec> {
243245
/// A response to a get BLOCKS_BY_ROOT request.
244246
BlocksByRoot(Arc<SignedBeaconBlock<T>>),
245247

248+
/// A response to a get LIGHTCLIENT_BOOTSTRAP request.
249+
LightClientBootstrap(LightClientBootstrap<T>),
250+
246251
/// A PONG response to a PING request.
247252
Pong(Ping),
248253

@@ -273,6 +278,12 @@ pub enum RPCCodedResponse<T: EthSpec> {
273278
StreamTermination(ResponseTermination),
274279
}
275280

281+
/// Request a light_client_bootstrap for lightclients peers.
282+
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
283+
pub struct LightClientBootstrapRequest {
284+
pub root: Hash256,
285+
}
286+
276287
/// The code assigned to an erroneous `RPCResponse`.
277288
#[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)]
278289
#[strum(serialize_all = "snake_case")]
@@ -321,6 +332,7 @@ impl<T: EthSpec> RPCCodedResponse<T> {
321332
RPCResponse::BlocksByRoot(_) => true,
322333
RPCResponse::Pong(_) => false,
323334
RPCResponse::MetaData(_) => false,
335+
RPCResponse::LightClientBootstrap(_) => false,
324336
},
325337
RPCCodedResponse::Error(_, _) => true,
326338
// Stream terminations are part of responses that have chunks
@@ -355,6 +367,7 @@ impl<T: EthSpec> RPCResponse<T> {
355367
RPCResponse::BlocksByRoot(_) => Protocol::BlocksByRoot,
356368
RPCResponse::Pong(_) => Protocol::Ping,
357369
RPCResponse::MetaData(_) => Protocol::MetaData,
370+
RPCResponse::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
358371
}
359372
}
360373
}
@@ -390,6 +403,9 @@ impl<T: EthSpec> std::fmt::Display for RPCResponse<T> {
390403
}
391404
RPCResponse::Pong(ping) => write!(f, "Pong: {}", ping.data),
392405
RPCResponse::MetaData(metadata) => write!(f, "Metadata: {}", metadata.seq_number()),
406+
RPCResponse::LightClientBootstrap(bootstrap) => {
407+
write!(f, "LightClientBootstrap Slot: {}", bootstrap.header.slot)
408+
}
393409
}
394410
}
395411
}

beacon_node/lighthouse_network/src/rpc/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ pub(crate) use protocol::{InboundRequest, RPCProtocol};
2626

2727
pub use handler::SubstreamId;
2828
pub use methods::{
29-
BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, MaxRequestBlocks,
30-
RPCResponseErrorCode, ResponseTermination, StatusMessage, MAX_REQUEST_BLOCKS,
29+
BlocksByRangeRequest, BlocksByRootRequest, GoodbyeReason, LightClientBootstrapRequest,
30+
MaxRequestBlocks, RPCResponseErrorCode, ResponseTermination, StatusMessage, MAX_REQUEST_BLOCKS,
3131
};
3232
pub(crate) use outbound::OutboundRequest;
3333
pub use protocol::{max_rpc_size, Protocol, RPCError};
@@ -108,18 +108,24 @@ pub struct RPC<Id: ReqId, TSpec: EthSpec> {
108108
/// Queue of events to be processed.
109109
events: Vec<NetworkBehaviourAction<RPCMessage<Id, TSpec>, RPCHandler<Id, TSpec>>>,
110110
fork_context: Arc<ForkContext>,
111+
enable_light_client_server: bool,
111112
/// Slog logger for RPC behaviour.
112113
log: slog::Logger,
113114
}
114115

115116
impl<Id: ReqId, TSpec: EthSpec> RPC<Id, TSpec> {
116-
pub fn new(fork_context: Arc<ForkContext>, log: slog::Logger) -> Self {
117+
pub fn new(
118+
fork_context: Arc<ForkContext>,
119+
enable_light_client_server: bool,
120+
log: slog::Logger,
121+
) -> Self {
117122
let log = log.new(o!("service" => "libp2p_rpc"));
118123
let limiter = RPCRateLimiterBuilder::new()
119124
.n_every(Protocol::MetaData, 2, Duration::from_secs(5))
120125
.n_every(Protocol::Ping, 2, Duration::from_secs(10))
121126
.n_every(Protocol::Status, 5, Duration::from_secs(15))
122127
.one_every(Protocol::Goodbye, Duration::from_secs(10))
128+
.one_every(Protocol::LightClientBootstrap, Duration::from_secs(10))
123129
.n_every(
124130
Protocol::BlocksByRange,
125131
methods::MAX_REQUEST_BLOCKS,
@@ -132,6 +138,7 @@ impl<Id: ReqId, TSpec: EthSpec> RPC<Id, TSpec> {
132138
limiter,
133139
events: Vec::new(),
134140
fork_context,
141+
enable_light_client_server,
135142
log,
136143
}
137144
}
@@ -188,6 +195,7 @@ where
188195
RPCProtocol {
189196
fork_context: self.fork_context.clone(),
190197
max_rpc_size: max_rpc_size(&self.fork_context),
198+
enable_light_client_server: self.enable_light_client_server,
191199
phantom: PhantomData,
192200
},
193201
(),

beacon_node/lighthouse_network/src/rpc/outbound.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub enum OutboundRequest<TSpec: EthSpec> {
3838
Goodbye(GoodbyeReason),
3939
BlocksByRange(OldBlocksByRangeRequest),
4040
BlocksByRoot(BlocksByRootRequest),
41+
LightClientBootstrap(LightClientBootstrapRequest),
4142
Ping(Ping),
4243
MetaData(PhantomData<TSpec>),
4344
}
@@ -84,9 +85,12 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
8485
ProtocolId::new(Protocol::MetaData, Version::V2, Encoding::SSZSnappy),
8586
ProtocolId::new(Protocol::MetaData, Version::V1, Encoding::SSZSnappy),
8687
],
88+
// Note: This match arm is technically unreachable as we only respond to light client requests
89+
// that we generate from the beacon state.
90+
// We do not make light client rpc requests from the beacon node
91+
OutboundRequest::LightClientBootstrap(_) => vec![],
8792
}
8893
}
89-
9094
/* These functions are used in the handler for stream management */
9195

9296
/// Number of responses expected for this request.
@@ -98,6 +102,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
98102
OutboundRequest::BlocksByRoot(req) => req.block_roots.len() as u64,
99103
OutboundRequest::Ping(_) => 1,
100104
OutboundRequest::MetaData(_) => 1,
105+
OutboundRequest::LightClientBootstrap(_) => 1,
101106
}
102107
}
103108

@@ -110,6 +115,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
110115
OutboundRequest::BlocksByRoot(_) => Protocol::BlocksByRoot,
111116
OutboundRequest::Ping(_) => Protocol::Ping,
112117
OutboundRequest::MetaData(_) => Protocol::MetaData,
118+
OutboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
113119
}
114120
}
115121

@@ -121,6 +127,7 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
121127
// variants that have `multiple_responses()` can have values.
122128
OutboundRequest::BlocksByRange(_) => ResponseTermination::BlocksByRange,
123129
OutboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot,
130+
OutboundRequest::LightClientBootstrap(_) => unreachable!(),
124131
OutboundRequest::Status(_) => unreachable!(),
125132
OutboundRequest::Goodbye(_) => unreachable!(),
126133
OutboundRequest::Ping(_) => unreachable!(),
@@ -178,6 +185,9 @@ impl<TSpec: EthSpec> std::fmt::Display for OutboundRequest<TSpec> {
178185
OutboundRequest::BlocksByRoot(req) => write!(f, "Blocks by root: {:?}", req),
179186
OutboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data),
180187
OutboundRequest::MetaData(_) => write!(f, "MetaData request"),
188+
OutboundRequest::LightClientBootstrap(bootstrap) => {
189+
write!(f, "Lightclient Bootstrap: {}", bootstrap.root)
190+
}
181191
}
182192
}
183193
}

0 commit comments

Comments
 (0)