mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 20:22:02 +00:00
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 <pawandhananjay@gmail.com>
This commit is contained in:
@@ -45,6 +45,7 @@ use beacon_chain::{BeaconChain, BeaconChainTypes, GossipVerifiedBlock};
|
||||
use derivative::Derivative;
|
||||
use futures::stream::{Stream, StreamExt};
|
||||
use futures::task::Poll;
|
||||
use lighthouse_network::rpc::LightClientBootstrapRequest;
|
||||
use lighthouse_network::{
|
||||
rpc::{BlocksByRangeRequest, BlocksByRootRequest, StatusMessage},
|
||||
Client, MessageId, NetworkGlobals, PeerId, PeerRequestId,
|
||||
@@ -156,6 +157,10 @@ const MAX_BLOCKS_BY_RANGE_QUEUE_LEN: usize = 1_024;
|
||||
/// will be stored before we start dropping them.
|
||||
const MAX_BLOCKS_BY_ROOTS_QUEUE_LEN: usize = 1_024;
|
||||
|
||||
/// The maximum number of queued `LightClientBootstrapRequest` objects received from the network RPC that
|
||||
/// will be stored before we start dropping them.
|
||||
const MAX_LIGHT_CLIENT_BOOTSTRAP_QUEUE_LEN: usize = 1_024;
|
||||
|
||||
/// The name of the manager tokio task.
|
||||
const MANAGER_TASK_NAME: &str = "beacon_processor_manager";
|
||||
|
||||
@@ -195,6 +200,7 @@ pub const CHAIN_SEGMENT: &str = "chain_segment";
|
||||
pub const STATUS_PROCESSING: &str = "status_processing";
|
||||
pub const BLOCKS_BY_RANGE_REQUEST: &str = "blocks_by_range_request";
|
||||
pub const BLOCKS_BY_ROOTS_REQUEST: &str = "blocks_by_roots_request";
|
||||
pub const LIGHT_CLIENT_BOOTSTRAP_REQUEST: &str = "light_client_bootstrap";
|
||||
pub const UNKNOWN_BLOCK_ATTESTATION: &str = "unknown_block_attestation";
|
||||
pub const UNKNOWN_BLOCK_AGGREGATE: &str = "unknown_block_aggregate";
|
||||
|
||||
@@ -557,6 +563,22 @@ impl<T: BeaconChainTypes> WorkEvent<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new work event to process `LightClientBootstrap`s from the RPC network.
|
||||
pub fn lightclient_bootstrap_request(
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
request: LightClientBootstrapRequest,
|
||||
) -> Self {
|
||||
Self {
|
||||
drop_during_sync: true,
|
||||
work: Work::LightClientBootstrapRequest {
|
||||
peer_id,
|
||||
request_id,
|
||||
request,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a `str` representation of the type of work this `WorkEvent` contains.
|
||||
pub fn work_type(&self) -> &'static str {
|
||||
self.work.str_id()
|
||||
@@ -733,6 +755,11 @@ pub enum Work<T: BeaconChainTypes> {
|
||||
request_id: PeerRequestId,
|
||||
request: BlocksByRootRequest,
|
||||
},
|
||||
LightClientBootstrapRequest {
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
request: LightClientBootstrapRequest,
|
||||
},
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> Work<T> {
|
||||
@@ -755,6 +782,7 @@ impl<T: BeaconChainTypes> Work<T> {
|
||||
Work::Status { .. } => STATUS_PROCESSING,
|
||||
Work::BlocksByRangeRequest { .. } => BLOCKS_BY_RANGE_REQUEST,
|
||||
Work::BlocksByRootsRequest { .. } => BLOCKS_BY_ROOTS_REQUEST,
|
||||
Work::LightClientBootstrapRequest { .. } => LIGHT_CLIENT_BOOTSTRAP_REQUEST,
|
||||
Work::UnknownBlockAttestation { .. } => UNKNOWN_BLOCK_ATTESTATION,
|
||||
Work::UnknownBlockAggregate { .. } => UNKNOWN_BLOCK_AGGREGATE,
|
||||
}
|
||||
@@ -898,7 +926,7 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
let mut status_queue = FifoQueue::new(MAX_STATUS_QUEUE_LEN);
|
||||
let mut bbrange_queue = FifoQueue::new(MAX_BLOCKS_BY_RANGE_QUEUE_LEN);
|
||||
let mut bbroots_queue = FifoQueue::new(MAX_BLOCKS_BY_ROOTS_QUEUE_LEN);
|
||||
|
||||
let mut lcbootstrap_queue = FifoQueue::new(MAX_LIGHT_CLIENT_BOOTSTRAP_QUEUE_LEN);
|
||||
// Channels for sending work to the re-process scheduler (`work_reprocessing_tx`) and to
|
||||
// receive them back once they are ready (`ready_work_rx`).
|
||||
let (ready_work_tx, ready_work_rx) = mpsc::channel(MAX_SCHEDULED_WORK_QUEUE_LEN);
|
||||
@@ -1137,6 +1165,8 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
} else if let Some(item) = backfill_chain_segment.pop() {
|
||||
self.spawn_worker(item, toolbox);
|
||||
// This statement should always be the final else statement.
|
||||
} else if let Some(item) = lcbootstrap_queue.pop() {
|
||||
self.spawn_worker(item, toolbox);
|
||||
} else {
|
||||
// Let the journal know that a worker is freed and there's nothing else
|
||||
// for it to do.
|
||||
@@ -1237,6 +1267,9 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
Work::BlocksByRootsRequest { .. } => {
|
||||
bbroots_queue.push(work, work_id, &self.log)
|
||||
}
|
||||
Work::LightClientBootstrapRequest { .. } => {
|
||||
lcbootstrap_queue.push(work, work_id, &self.log)
|
||||
}
|
||||
Work::UnknownBlockAttestation { .. } => {
|
||||
unknown_block_attestation_queue.push(work)
|
||||
}
|
||||
@@ -1594,6 +1627,16 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
request,
|
||||
)
|
||||
}),
|
||||
/*
|
||||
* Processing of lightclient bootstrap requests from other peers.
|
||||
*/
|
||||
Work::LightClientBootstrapRequest {
|
||||
peer_id,
|
||||
request_id,
|
||||
request,
|
||||
} => task_spawner.spawn_blocking(move || {
|
||||
worker.handle_light_client_bootstrap(peer_id, request_id, request)
|
||||
}),
|
||||
Work::UnknownBlockAttestation {
|
||||
message_id,
|
||||
peer_id,
|
||||
|
||||
@@ -11,7 +11,7 @@ use slog::{debug, error};
|
||||
use slot_clock::SlotClock;
|
||||
use std::sync::Arc;
|
||||
use task_executor::TaskExecutor;
|
||||
use types::{Epoch, EthSpec, Hash256, Slot};
|
||||
use types::{light_client_bootstrap::LightClientBootstrap, Epoch, EthSpec, Hash256, Slot};
|
||||
|
||||
use super::Worker;
|
||||
|
||||
@@ -204,6 +204,79 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Handle a `BlocksByRoot` request from the peer.
|
||||
pub fn handle_light_client_bootstrap(
|
||||
self,
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
request: LightClientBootstrapRequest,
|
||||
) {
|
||||
let block_root = request.root;
|
||||
let state_root = match self.chain.get_blinded_block(&block_root) {
|
||||
Ok(signed_block) => match signed_block {
|
||||
Some(signed_block) => signed_block.state_root(),
|
||||
None => {
|
||||
self.send_error_response(
|
||||
peer_id,
|
||||
RPCResponseErrorCode::ResourceUnavailable,
|
||||
"Bootstrap not avaiable".into(),
|
||||
request_id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
self.send_error_response(
|
||||
peer_id,
|
||||
RPCResponseErrorCode::ResourceUnavailable,
|
||||
"Bootstrap not avaiable".into(),
|
||||
request_id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let mut beacon_state = match self.chain.get_state(&state_root, None) {
|
||||
Ok(beacon_state) => match beacon_state {
|
||||
Some(state) => state,
|
||||
None => {
|
||||
self.send_error_response(
|
||||
peer_id,
|
||||
RPCResponseErrorCode::ResourceUnavailable,
|
||||
"Bootstrap not avaiable".into(),
|
||||
request_id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
self.send_error_response(
|
||||
peer_id,
|
||||
RPCResponseErrorCode::ResourceUnavailable,
|
||||
"Bootstrap not avaiable".into(),
|
||||
request_id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let bootstrap = match LightClientBootstrap::from_beacon_state(&mut beacon_state) {
|
||||
Ok(bootstrap) => bootstrap,
|
||||
Err(_) => {
|
||||
self.send_error_response(
|
||||
peer_id,
|
||||
RPCResponseErrorCode::ResourceUnavailable,
|
||||
"Bootstrap not avaiable".into(),
|
||||
request_id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
self.send_response(
|
||||
peer_id,
|
||||
Response::LightClientBootstrap(bootstrap),
|
||||
request_id,
|
||||
)
|
||||
}
|
||||
|
||||
/// Handle a `BlocksByRange` request from the peer.
|
||||
pub fn handle_blocks_by_range_request(
|
||||
self,
|
||||
|
||||
@@ -168,6 +168,9 @@ impl<T: BeaconChainTypes> Router<T> {
|
||||
Request::BlocksByRoot(request) => self
|
||||
.processor
|
||||
.on_blocks_by_root_request(peer_id, id, request),
|
||||
Request::LightClientBootstrap(request) => self
|
||||
.processor
|
||||
.on_lightclient_bootstrap(peer_id, id, request),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +195,7 @@ impl<T: BeaconChainTypes> Router<T> {
|
||||
self.processor
|
||||
.on_blocks_by_root_response(peer_id, request_id, beacon_block);
|
||||
}
|
||||
Response::LightClientBootstrap(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,18 @@ impl<T: BeaconChainTypes> Processor<T> {
|
||||
))
|
||||
}
|
||||
|
||||
/// Handle a `LightClientBootstrap` request from the peer.
|
||||
pub fn on_lightclient_bootstrap(
|
||||
&mut self,
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
request: LightClientBootstrapRequest,
|
||||
) {
|
||||
self.send_beacon_processor_work(BeaconWorkEvent::lightclient_bootstrap_request(
|
||||
peer_id, request_id, request,
|
||||
))
|
||||
}
|
||||
|
||||
/// Handle a `BlocksByRange` request from the peer.
|
||||
pub fn on_blocks_by_range_request(
|
||||
&mut self,
|
||||
|
||||
Reference in New Issue
Block a user