mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 20:22:02 +00:00
compile
This commit is contained in:
@@ -45,7 +45,7 @@ use beacon_chain::{BeaconChain, BeaconChainTypes, GossipVerifiedBlock};
|
||||
use derivative::Derivative;
|
||||
use futures::stream::{Stream, StreamExt};
|
||||
use futures::task::Poll;
|
||||
use lighthouse_network::rpc::methods::TxBlobsByRangeRequest;
|
||||
use lighthouse_network::rpc::methods::BlobsByRangeRequest;
|
||||
use lighthouse_network::{
|
||||
rpc::{BlocksByRangeRequest, BlocksByRootRequest, StatusMessage},
|
||||
Client, MessageId, NetworkGlobals, PeerId, PeerRequestId,
|
||||
@@ -66,6 +66,7 @@ use types::{
|
||||
SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof, SignedVoluntaryExit,
|
||||
SubnetId, SyncCommitteeMessage, SyncSubnetId,
|
||||
};
|
||||
use types::signed_blobs_sidecar::SignedBlobsSidecar;
|
||||
use work_reprocessing_queue::{
|
||||
spawn_reprocess_scheduler, QueuedAggregate, QueuedRpcBlock, QueuedUnaggregate, ReadyWork,
|
||||
};
|
||||
@@ -190,7 +191,7 @@ pub const GOSSIP_ATTESTATION_BATCH: &str = "gossip_attestation_batch";
|
||||
pub const GOSSIP_AGGREGATE: &str = "gossip_aggregate";
|
||||
pub const GOSSIP_AGGREGATE_BATCH: &str = "gossip_aggregate_batch";
|
||||
pub const GOSSIP_BLOCK: &str = "gossip_block";
|
||||
pub const GOSSIP_BLOB: &str = "gossip_blob";
|
||||
pub const GOSSIP_BLOBS_SIDECAR: &str = "gossip_blobs_sidecar";
|
||||
pub const DELAYED_IMPORT_BLOCK: &str = "delayed_import_block";
|
||||
pub const GOSSIP_VOLUNTARY_EXIT: &str = "gossip_voluntary_exit";
|
||||
pub const GOSSIP_PROPOSER_SLASHING: &str = "gossip_proposer_slashing";
|
||||
@@ -201,8 +202,8 @@ pub const RPC_BLOCK: &str = "rpc_block";
|
||||
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 TX_BLOBS_BY_RANGE_REQUEST: &str = "tx_blobs_by_range_request";
|
||||
pub const BLOCKS_BY_ROOTS_REQUEST: &str = "blocks_by_roots_request";
|
||||
pub const BLOBS_BY_RANGE_REQUEST: &str = "blobs_by_range_request";
|
||||
pub const UNKNOWN_BLOCK_ATTESTATION: &str = "unknown_block_attestation";
|
||||
pub const UNKNOWN_BLOCK_AGGREGATE: &str = "unknown_block_aggregate";
|
||||
|
||||
@@ -408,20 +409,21 @@ impl<T: BeaconChainTypes> WorkEvent<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gossip_tx_blob_block(
|
||||
/// Create a new `Work` event for some blobs sidecar.
|
||||
pub fn gossip_blobs_sidecar(
|
||||
message_id: MessageId,
|
||||
peer_id: PeerId,
|
||||
peer_client: Client,
|
||||
blob: Box<BlobsSidecar<T::EthSpec>>,
|
||||
blobs: Arc<SignedBlobsSidecar<T::EthSpec>>,
|
||||
seen_timestamp: Duration,
|
||||
) -> Self {
|
||||
Self {
|
||||
drop_during_sync: false,
|
||||
work: Work::GossipBlob {
|
||||
work: Work::GossipBlobsSidecar {
|
||||
message_id,
|
||||
peer_id,
|
||||
peer_client,
|
||||
blob,
|
||||
blobs,
|
||||
seen_timestamp,
|
||||
},
|
||||
}
|
||||
@@ -599,6 +601,21 @@ impl<T: BeaconChainTypes> WorkEvent<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blobs_by_range_request(
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
request: BlobsByRangeRequest,
|
||||
) -> Self {
|
||||
Self {
|
||||
drop_during_sync: false,
|
||||
work: Work::BlobsByRangeRequest {
|
||||
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()
|
||||
@@ -717,6 +734,13 @@ pub enum Work<T: BeaconChainTypes> {
|
||||
block: Arc<SignedBeaconBlock<T::EthSpec>>,
|
||||
seen_timestamp: Duration,
|
||||
},
|
||||
GossipBlobsSidecar {
|
||||
message_id: MessageId,
|
||||
peer_id: PeerId,
|
||||
peer_client: Client,
|
||||
blobs: Arc<SignedBlobsSidecar<T::EthSpec>>,
|
||||
seen_timestamp: Duration,
|
||||
},
|
||||
GossipBlob {
|
||||
message_id: MessageId,
|
||||
peer_id: PeerId,
|
||||
@@ -787,6 +811,11 @@ pub enum Work<T: BeaconChainTypes> {
|
||||
request_id: PeerRequestId,
|
||||
request: BlocksByRootRequest,
|
||||
},
|
||||
BlobsByRangeRequest {
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
request: BlobsByRangeRequest,
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BeaconChainTypes> Work<T> {
|
||||
@@ -798,7 +827,7 @@ impl<T: BeaconChainTypes> Work<T> {
|
||||
Work::GossipAggregate { .. } => GOSSIP_AGGREGATE,
|
||||
Work::GossipAggregateBatch { .. } => GOSSIP_AGGREGATE_BATCH,
|
||||
Work::GossipBlock { .. } => GOSSIP_BLOCK,
|
||||
Work::GossipBlob { .. } => GOSSIP_BLOB,
|
||||
Work::GossipBlobsSidecar { .. } => GOSSIP_BLOBS_SIDECAR,
|
||||
Work::DelayedImportBlock { .. } => DELAYED_IMPORT_BLOCK,
|
||||
Work::GossipVoluntaryExit { .. } => GOSSIP_VOLUNTARY_EXIT,
|
||||
Work::GossipProposerSlashing { .. } => GOSSIP_PROPOSER_SLASHING,
|
||||
@@ -811,6 +840,7 @@ impl<T: BeaconChainTypes> Work<T> {
|
||||
Work::BlocksByRangeRequest { .. } => BLOCKS_BY_RANGE_REQUEST,
|
||||
Work::TxBlobsByRangeRequest { .. } => TX_BLOBS_BY_RANGE_REQUEST,
|
||||
Work::BlocksByRootsRequest { .. } => BLOCKS_BY_ROOTS_REQUEST,
|
||||
Work::BlobsByRangeRequest {..} => BLOBS_BY_RANGE_REQUEST,
|
||||
Work::UnknownBlockAttestation { .. } => UNKNOWN_BLOCK_ATTESTATION,
|
||||
Work::UnknownBlockAggregate { .. } => UNKNOWN_BLOCK_AGGREGATE,
|
||||
}
|
||||
@@ -949,13 +979,14 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
let mut chain_segment_queue = FifoQueue::new(MAX_CHAIN_SEGMENT_QUEUE_LEN);
|
||||
let mut backfill_chain_segment = FifoQueue::new(MAX_CHAIN_SEGMENT_QUEUE_LEN);
|
||||
let mut gossip_block_queue = FifoQueue::new(MAX_GOSSIP_BLOCK_QUEUE_LEN);
|
||||
let mut gossip_blob_queue = FifoQueue::new(MAX_GOSSIP_BLOB_QUEUE_LEN);
|
||||
let mut gossip_blobs_sidecar_queue = FifoQueue::new(MAX_GOSSIP_BLOCK_QUEUE_LEN);
|
||||
let mut delayed_block_queue = FifoQueue::new(MAX_DELAYED_BLOCK_QUEUE_LEN);
|
||||
|
||||
let mut status_queue = FifoQueue::new(MAX_STATUS_QUEUE_LEN);
|
||||
let mut bbrange_queue = FifoQueue::new(MAX_BLOCKS_BY_RANGE_QUEUE_LEN);
|
||||
let mut txbbrange_queue = FifoQueue::new(MAX_TX_BLOBS_BY_RANGE_QUEUE_LEN);
|
||||
let mut bbroots_queue = FifoQueue::new(MAX_BLOCKS_BY_ROOTS_QUEUE_LEN);
|
||||
let mut blbrange_queue = FifoQueue::new(MAX_BLOCKS_BY_ROOTS_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`).
|
||||
@@ -1267,8 +1298,8 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
Work::GossipBlock { .. } => {
|
||||
gossip_block_queue.push(work, work_id, &self.log)
|
||||
}
|
||||
Work::GossipBlob { .. } => {
|
||||
gossip_blob_queue.push(work, work_id, &self.log)
|
||||
Work::GossipBlobsSidecar { .. } => {
|
||||
gossip_blobs_sidecar_queue.push(work, work_id, &self.log)
|
||||
}
|
||||
Work::DelayedImportBlock { .. } => {
|
||||
delayed_block_queue.push(work, work_id, &self.log)
|
||||
@@ -1306,6 +1337,9 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
Work::BlocksByRootsRequest { .. } => {
|
||||
bbroots_queue.push(work, work_id, &self.log)
|
||||
}
|
||||
Work::BlobsByRangeRequest { .. } => {
|
||||
blbrange_queue.push(work, work_id, &self.log)
|
||||
}
|
||||
Work::UnknownBlockAttestation { .. } => {
|
||||
unknown_block_attestation_queue.push(work)
|
||||
}
|
||||
@@ -1526,6 +1560,28 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
)
|
||||
.await
|
||||
}),
|
||||
/*
|
||||
* Verification for blobs sidecars received on gossip.
|
||||
*/
|
||||
Work::GossipBlobsSidecar {
|
||||
message_id,
|
||||
peer_id,
|
||||
peer_client,
|
||||
blobs,
|
||||
seen_timestamp,
|
||||
} => task_spawner.spawn_async(async move {
|
||||
worker
|
||||
.process_gossip_blobs_sidecar(
|
||||
message_id,
|
||||
peer_id,
|
||||
peer_client,
|
||||
blobs,
|
||||
work_reprocessing_tx,
|
||||
duplicate_cache,
|
||||
seen_timestamp,
|
||||
)
|
||||
.await
|
||||
}),
|
||||
/*
|
||||
* Import for blocks that we received earlier than their intended slot.
|
||||
*/
|
||||
@@ -1664,6 +1720,21 @@ impl<T: BeaconChainTypes> BeaconProcessor<T> {
|
||||
request,
|
||||
)
|
||||
}),
|
||||
|
||||
Work::BlobsByRangeRequest {
|
||||
peer_id,
|
||||
request_id,
|
||||
request
|
||||
} => task_spawner.spawn_blocking_with_manual_send_idle(move |send_idle_on_drop| {
|
||||
worker.handle_blobs_by_range_request(
|
||||
sub_executor,
|
||||
send_idle_on_drop,
|
||||
peer_id,
|
||||
request_id,
|
||||
request,
|
||||
)
|
||||
}),
|
||||
|
||||
Work::UnknownBlockAttestation {
|
||||
message_id,
|
||||
peer_id,
|
||||
|
||||
@@ -22,6 +22,7 @@ use types::{
|
||||
ProposerSlashing, SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof,
|
||||
SignedVoluntaryExit, Slot, SubnetId, SyncCommitteeMessage, SyncSubnetId,
|
||||
};
|
||||
use types::signed_blobs_sidecar::SignedBlobsSidecar;
|
||||
|
||||
use super::{
|
||||
super::work_reprocessing_queue::{
|
||||
@@ -672,6 +673,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
.await
|
||||
{
|
||||
let block_root = gossip_verified_block.block_root;
|
||||
|
||||
if let Some(handle) = duplicate_cache.check_and_insert(block_root) {
|
||||
self.process_gossip_verified_block(
|
||||
peer_id,
|
||||
@@ -784,6 +786,9 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
|
||||
verified_block
|
||||
}
|
||||
Err(BlockError::MissingSidecar) => {
|
||||
todo!(); //is relevant?
|
||||
}
|
||||
Err(BlockError::ParentUnknown(block)) => {
|
||||
debug!(
|
||||
self.log,
|
||||
@@ -946,6 +951,22 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
let block: Arc<_> = verified_block.block.clone();
|
||||
let block_root = verified_block.block_root;
|
||||
|
||||
let sidecar = if verified_block.block.message()
|
||||
.body().blob_kzg_commitments().map(|committments| committments.is_empty()).unwrap_or(true) {
|
||||
None
|
||||
} else if let Some(sidecar) = self.chain.sidecar_waiting_for_block.lock().as_ref() {
|
||||
if sidecar.message.beacon_block_root == verified_block.block_root() {
|
||||
Some(sidecar.clone())
|
||||
} else {
|
||||
*self.chain.block_waiting_for_sidecar.lock() = Some(verified_block);
|
||||
return
|
||||
}
|
||||
} else {
|
||||
*self.chain.block_waiting_for_sidecar.lock() = Some(verified_block);
|
||||
// we need the sidecar but dont have it yet
|
||||
return
|
||||
};
|
||||
|
||||
match self
|
||||
.chain
|
||||
.process_block(block_root, verified_block, CountUnrealized::True)
|
||||
@@ -954,31 +975,31 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
Ok(block_root) => {
|
||||
metrics::inc_counter(&metrics::BEACON_PROCESSOR_GOSSIP_BLOCK_IMPORTED_TOTAL);
|
||||
|
||||
if reprocess_tx
|
||||
.try_send(ReprocessQueueMessage::BlockImported(block_root))
|
||||
.is_err()
|
||||
{
|
||||
error!(
|
||||
if reprocess_tx
|
||||
.try_send(ReprocessQueueMessage::BlockImported(block_root))
|
||||
.is_err()
|
||||
{
|
||||
error!(
|
||||
self.log,
|
||||
"Failed to inform block import";
|
||||
"source" => "gossip",
|
||||
"block_root" => ?block_root,
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
debug!(
|
||||
debug!(
|
||||
self.log,
|
||||
"Gossipsub block processed";
|
||||
"block" => ?block_root,
|
||||
"peer_id" => %peer_id
|
||||
);
|
||||
|
||||
self.chain.recompute_head_at_current_slot().await;
|
||||
}
|
||||
Err(BlockError::ParentUnknown { .. }) => {
|
||||
// Inform the sync manager to find parents for this block
|
||||
// This should not occur. It should be checked by `should_forward_block`
|
||||
error!(
|
||||
self.chain.recompute_head_at_current_slot().await;
|
||||
}
|
||||
Err(BlockError::ParentUnknown { .. }) => {
|
||||
// Inform the sync manager to find parents for this block
|
||||
// This should not occur. It should be checked by `should_forward_block`
|
||||
error!(
|
||||
self.log,
|
||||
"Block with unknown parent attempted to be processed";
|
||||
"peer_id" => %peer_id
|
||||
@@ -991,27 +1012,31 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
"Failed to verify execution payload";
|
||||
"error" => %e
|
||||
);
|
||||
}
|
||||
other => {
|
||||
debug!(
|
||||
}
|
||||
other => {
|
||||
debug!(
|
||||
self.log,
|
||||
"Invalid gossip beacon block";
|
||||
"outcome" => ?other,
|
||||
"block root" => ?block_root,
|
||||
"block slot" => block.slot()
|
||||
);
|
||||
self.gossip_penalize_peer(
|
||||
peer_id,
|
||||
PeerAction::MidToleranceError,
|
||||
"bad_gossip_block_ssz",
|
||||
);
|
||||
trace!(
|
||||
self.gossip_penalize_peer(
|
||||
peer_id,
|
||||
PeerAction::MidToleranceError,
|
||||
"bad_gossip_block_ssz",
|
||||
);
|
||||
trace!(
|
||||
self.log,
|
||||
"Invalid gossip beacon block ssz";
|
||||
"ssz" => format_args!("0x{}", hex::encode(block.as_ssz_bytes())),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
} else {
|
||||
*self.chain.sidecar_waiting_for_block.lock() = Some(blobs);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_gossip_voluntary_exit(
|
||||
|
||||
@@ -6,13 +6,14 @@ use beacon_chain::{BeaconChainError, BeaconChainTypes, HistoricalBlockError, Whe
|
||||
use itertools::process_results;
|
||||
use lighthouse_network::rpc::StatusMessage;
|
||||
use lighthouse_network::rpc::*;
|
||||
use lighthouse_network::rpc::methods::BlobsByRangeRequest;
|
||||
use lighthouse_network::{PeerId, PeerRequestId, ReportSource, Response, SyncInfo};
|
||||
use slog::{debug, error};
|
||||
use lighthouse_network::rpc::methods::TxBlobsByRangeRequest;
|
||||
use slot_clock::SlotClock;
|
||||
use std::sync::Arc;
|
||||
use task_executor::TaskExecutor;
|
||||
use types::{Epoch, EthSpec, Hash256, Slot};
|
||||
use types::{Epoch, EthSpec, Hash256, Slot, VariableList};
|
||||
|
||||
use super::Worker;
|
||||
|
||||
@@ -382,4 +383,150 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
"load_blocks_by_range_blocks",
|
||||
);
|
||||
}
|
||||
|
||||
/// Handle a `BlobsByRange` request from the peer.
|
||||
pub fn handle_blobs_by_range_request(
|
||||
self,
|
||||
executor: TaskExecutor,
|
||||
send_on_drop: SendOnDrop,
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
mut req: BlobsByRangeRequest,
|
||||
) {
|
||||
debug!(self.log, "Received BlobsByRange Request";
|
||||
"peer_id" => %peer_id,
|
||||
"count" => req.count,
|
||||
"start_slot" => req.start_slot,
|
||||
);
|
||||
|
||||
// Should not send more than max request blocks
|
||||
if req.count > MAX_REQUEST_BLOCKS {
|
||||
req.count = MAX_REQUEST_BLOCKS;
|
||||
}
|
||||
|
||||
let forwards_block_root_iter = match self
|
||||
.chain
|
||||
.forwards_iter_block_roots(Slot::from(req.start_slot))
|
||||
{
|
||||
Ok(iter) => iter,
|
||||
Err(BeaconChainError::HistoricalBlockError(
|
||||
HistoricalBlockError::BlockOutOfRange {
|
||||
slot,
|
||||
oldest_block_slot,
|
||||
},
|
||||
)) => {
|
||||
debug!(self.log, "Range request failed during backfill"; "requested_slot" => slot, "oldest_known_slot" => oldest_block_slot);
|
||||
return self.send_error_response(
|
||||
peer_id,
|
||||
RPCResponseErrorCode::ResourceUnavailable,
|
||||
"Backfilling".into(),
|
||||
request_id,
|
||||
);
|
||||
}
|
||||
Err(e) => return error!(self.log, "Unable to obtain root iter"; "error" => ?e),
|
||||
};
|
||||
|
||||
// Pick out the required blocks, ignoring skip-slots.
|
||||
let mut last_block_root = None;
|
||||
let maybe_block_roots = process_results(forwards_block_root_iter, |iter| {
|
||||
iter.take_while(|(_, slot)| slot.as_u64() < req.start_slot.saturating_add(req.count))
|
||||
// map skip slots to None
|
||||
.map(|(root, _)| {
|
||||
let result = if Some(root) == last_block_root {
|
||||
None
|
||||
} else {
|
||||
Some(root)
|
||||
};
|
||||
last_block_root = Some(root);
|
||||
result
|
||||
})
|
||||
.collect::<Vec<Option<Hash256>>>()
|
||||
});
|
||||
|
||||
let block_roots = match maybe_block_roots {
|
||||
Ok(block_roots) => block_roots,
|
||||
Err(e) => return error!(self.log, "Error during iteration over blocks"; "error" => ?e),
|
||||
};
|
||||
|
||||
// remove all skip slots
|
||||
let block_roots = block_roots.into_iter().flatten().collect::<Vec<_>>();
|
||||
|
||||
// Fetching blocks is async because it may have to hit the execution layer for payloads.
|
||||
executor.spawn(
|
||||
async move {
|
||||
let mut blocks_sent = 0;
|
||||
let mut send_response = true;
|
||||
|
||||
for root in block_roots {
|
||||
match self.chain.store.get_blobs(&root) {
|
||||
Ok(Some(blob)) => {
|
||||
blocks_sent += 1;
|
||||
self.send_network_message(NetworkMessage::SendResponse {
|
||||
peer_id,
|
||||
response: Response::BlobsByRange(Some(Arc::new(VariableList::new(vec![blob.message]).unwrap()))),
|
||||
id: request_id,
|
||||
});
|
||||
}
|
||||
Ok(None) => {
|
||||
error!(
|
||||
self.log,
|
||||
"Blob in the chain is not in the store";
|
||||
"request_root" => ?root
|
||||
);
|
||||
break;
|
||||
}
|
||||
Err(e) => {
|
||||
error!(
|
||||
self.log,
|
||||
"Error fetching block for peer";
|
||||
"block_root" => ?root,
|
||||
"error" => ?e
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let current_slot = self
|
||||
.chain
|
||||
.slot()
|
||||
.unwrap_or_else(|_| self.chain.slot_clock.genesis_slot());
|
||||
|
||||
if blocks_sent < (req.count as usize) {
|
||||
debug!(
|
||||
self.log,
|
||||
"BlocksByRange Response processed";
|
||||
"peer" => %peer_id,
|
||||
"msg" => "Failed to return all requested blocks",
|
||||
"start_slot" => req.start_slot,
|
||||
"current_slot" => current_slot,
|
||||
"requested" => req.count,
|
||||
"returned" => blocks_sent
|
||||
);
|
||||
} else {
|
||||
debug!(
|
||||
self.log,
|
||||
"BlocksByRange Response processed";
|
||||
"peer" => %peer_id,
|
||||
"start_slot" => req.start_slot,
|
||||
"current_slot" => current_slot,
|
||||
"requested" => req.count,
|
||||
"returned" => blocks_sent
|
||||
);
|
||||
}
|
||||
|
||||
if send_response {
|
||||
// send the stream terminator
|
||||
self.send_network_message(NetworkMessage::SendResponse {
|
||||
peer_id,
|
||||
response: Response::BlobsByRange(None),
|
||||
id: request_id,
|
||||
});
|
||||
}
|
||||
|
||||
drop(send_on_drop);
|
||||
},
|
||||
"load_blocks_by_range_blocks",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user