Merge branch 'unstable' into deneb-merge-from-unstable-20230627
# Conflicts: # beacon_node/beacon_chain/src/beacon_chain.rs # beacon_node/beacon_chain/src/block_verification.rs # beacon_node/beacon_chain/src/lib.rs # beacon_node/beacon_chain/src/test_utils.rs # beacon_node/beacon_chain/tests/block_verification.rs # beacon_node/beacon_chain/tests/store_tests.rs # beacon_node/beacon_chain/tests/tests.rs # beacon_node/http_api/src/publish_blocks.rs # beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs # beacon_node/lighthouse_network/src/rpc/methods.rs # beacon_node/lighthouse_network/src/rpc/outbound.rs # beacon_node/lighthouse_network/src/rpc/protocol.rs # beacon_node/lighthouse_network/src/service/api_types.rs # beacon_node/network/src/beacon_processor/worker/gossip_methods.rs # beacon_node/network/src/beacon_processor/worker/rpc_methods.rs # beacon_node/network/src/beacon_processor/worker/sync_methods.rs # beacon_node/network/src/sync/block_lookups/single_block_lookup.rs # beacon_node/network/src/sync/network_context.rs # beacon_node/network/src/sync/range_sync/batch.rs # beacon_node/network/src/sync/range_sync/chain.rs # common/eth2/src/types.rs # consensus/fork_choice/src/fork_choice.rs
This commit is contained in:
@@ -71,7 +71,6 @@ use execution_layer::{
|
||||
BlockProposalContents, BuilderParams, ChainHealth, ExecutionLayer, FailedCondition,
|
||||
PayloadAttributes, PayloadStatus,
|
||||
};
|
||||
pub use fork_choice::CountUnrealized;
|
||||
use fork_choice::{
|
||||
AttestationFromBlock, ExecutionStatus, ForkChoice, ForkchoiceUpdateParameters,
|
||||
InvalidationOperation, PayloadVerificationStatus, ResetPayloadStatuses,
|
||||
@@ -2599,7 +2598,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub async fn process_chain_segment(
|
||||
self: &Arc<Self>,
|
||||
chain_segment: Vec<BlockWrapper<T::EthSpec>>,
|
||||
count_unrealized: CountUnrealized,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> ChainSegmentResult<T::EthSpec> {
|
||||
let mut imported_blocks = 0;
|
||||
@@ -2666,7 +2664,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.process_block(
|
||||
signature_verified_block.block_root(),
|
||||
signature_verified_block,
|
||||
count_unrealized,
|
||||
notify_execution_layer,
|
||||
)
|
||||
.await
|
||||
@@ -2759,13 +2756,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
pub async fn process_blob(
|
||||
self: &Arc<Self>,
|
||||
blob: GossipVerifiedBlob<T::EthSpec>,
|
||||
count_unrealized: CountUnrealized,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
self.check_availability_and_maybe_import(
|
||||
blob.slot(),
|
||||
|chain| chain.data_availability_checker.put_gossip_blob(blob),
|
||||
count_unrealized,
|
||||
)
|
||||
self.check_availability_and_maybe_import(blob.slot(), |chain| {
|
||||
chain.data_availability_checker.put_gossip_blob(blob)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -2789,7 +2783,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
self: &Arc<Self>,
|
||||
block_root: Hash256,
|
||||
unverified_block: B,
|
||||
count_unrealized: CountUnrealized,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
// Start the Prometheus timer.
|
||||
@@ -2813,20 +2806,13 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
.map_err(|e| self.handle_block_error(e))?;
|
||||
|
||||
match executed_block {
|
||||
ExecutedBlock::Available(block) => {
|
||||
self.import_available_block(Box::new(block), count_unrealized)
|
||||
.await
|
||||
}
|
||||
ExecutedBlock::Available(block) => self.import_available_block(Box::new(block)).await,
|
||||
ExecutedBlock::AvailabilityPending(block) => {
|
||||
self.check_availability_and_maybe_import(
|
||||
block.block.slot(),
|
||||
|chain| {
|
||||
chain
|
||||
.data_availability_checker
|
||||
.put_pending_executed_block(block)
|
||||
},
|
||||
count_unrealized,
|
||||
)
|
||||
self.check_availability_and_maybe_import(block.block.slot(), |chain| {
|
||||
chain
|
||||
.data_availability_checker
|
||||
.put_pending_executed_block(block)
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -2836,7 +2822,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
/// get a fully `ExecutedBlock`
|
||||
///
|
||||
/// An error is returned if the verification handle couldn't be awaited.
|
||||
async fn into_executed_block(
|
||||
pub async fn into_executed_block(
|
||||
self: Arc<Self>,
|
||||
execution_pending_block: ExecutionPendingBlock<T>,
|
||||
) -> Result<ExecutedBlock<T::EthSpec>, BlockError<T::EthSpec>> {
|
||||
@@ -2925,13 +2911,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
self: &Arc<Self>,
|
||||
slot: Slot,
|
||||
cache_fn: impl FnOnce(Arc<Self>) -> Result<Availability<T::EthSpec>, AvailabilityCheckError>,
|
||||
count_unrealized: CountUnrealized,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
let availability = cache_fn(self.clone())?;
|
||||
match availability {
|
||||
Availability::Available(block) => {
|
||||
self.import_available_block(block, count_unrealized).await
|
||||
}
|
||||
Availability::Available(block) => self.import_available_block(block).await,
|
||||
Availability::MissingComponents(block_root) => Ok(
|
||||
AvailabilityProcessingStatus::MissingComponents(slot, block_root),
|
||||
),
|
||||
@@ -2941,7 +2924,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
async fn import_available_block(
|
||||
self: &Arc<Self>,
|
||||
block: Box<AvailableExecutedBlock<T::EthSpec>>,
|
||||
count_unrealized: CountUnrealized,
|
||||
) -> Result<AvailabilityProcessingStatus, BlockError<T::EthSpec>> {
|
||||
let AvailableExecutedBlock {
|
||||
block,
|
||||
@@ -2971,7 +2953,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
state,
|
||||
confirmed_state_roots,
|
||||
payload_verification_outcome.payload_verification_status,
|
||||
count_unrealized,
|
||||
parent_block,
|
||||
parent_eth1_finalization_data,
|
||||
consensus_context,
|
||||
@@ -3017,7 +2998,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
mut state: BeaconState<T::EthSpec>,
|
||||
confirmed_state_roots: Vec<Hash256>,
|
||||
payload_verification_status: PayloadVerificationStatus,
|
||||
count_unrealized: CountUnrealized,
|
||||
parent_block: SignedBlindedBeaconBlock<T::EthSpec>,
|
||||
parent_eth1_finalization_data: Eth1FinalizationData,
|
||||
mut consensus_context: ConsensusContext<T::EthSpec>,
|
||||
@@ -3088,7 +3068,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
||||
&state,
|
||||
payload_verification_status,
|
||||
&self.spec,
|
||||
count_unrealized,
|
||||
)
|
||||
.map_err(|e| BlockError::BeaconChainError(e.into()))?;
|
||||
}
|
||||
|
||||
@@ -149,8 +149,6 @@ pub enum BlockError<T: EthSpec> {
|
||||
/// It's unclear if this block is valid, but it cannot be processed without already knowing
|
||||
/// its parent.
|
||||
ParentUnknown(BlockWrapper<T>),
|
||||
/// The block skips too many slots and is a DoS risk.
|
||||
TooManySkippedSlots { parent_slot: Slot, block_slot: Slot },
|
||||
/// The block slot is greater than the present slot.
|
||||
///
|
||||
/// ## Peer scoring
|
||||
@@ -951,9 +949,6 @@ impl<T: BeaconChainTypes> GossipVerifiedBlock<T> {
|
||||
parent_block.root
|
||||
};
|
||||
|
||||
// Reject any block that exceeds our limit on skipped slots.
|
||||
check_block_skip_slots(chain, parent_block.slot, block.message())?;
|
||||
|
||||
// We assign to a variable instead of using `if let Some` directly to ensure we drop the
|
||||
// write lock before trying to acquire it again in the `else` clause.
|
||||
let proposer_opt = chain
|
||||
@@ -1110,9 +1105,6 @@ impl<T: BeaconChainTypes> SignatureVerifiedBlock<T> {
|
||||
|
||||
let (mut parent, block) = load_parent(block_root, block, chain)?;
|
||||
|
||||
// Reject any block that exceeds our limit on skipped slots.
|
||||
check_block_skip_slots(chain, parent.beacon_block.slot(), block.message())?;
|
||||
|
||||
let state = cheap_state_advance_to_obtain_committees(
|
||||
&mut parent.pre_state,
|
||||
parent.beacon_state_root,
|
||||
@@ -1327,9 +1319,6 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||
return Err(BlockError::ParentUnknown(block.into_block_wrapper()));
|
||||
}
|
||||
|
||||
// Reject any block that exceeds our limit on skipped slots.
|
||||
check_block_skip_slots(chain, parent.beacon_block.slot(), block.message())?;
|
||||
|
||||
/*
|
||||
* Perform cursory checks to see if the block is even worth processing.
|
||||
*/
|
||||
@@ -1688,30 +1677,6 @@ impl<T: BeaconChainTypes> ExecutionPendingBlock<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the count of skip slots between the block and its parent does not exceed our maximum
|
||||
/// value.
|
||||
///
|
||||
/// Whilst this is not part of the specification, we include this to help prevent us from DoS
|
||||
/// attacks. In times of dire network circumstance, the user can configure the
|
||||
/// `import_max_skip_slots` value.
|
||||
fn check_block_skip_slots<T: BeaconChainTypes>(
|
||||
chain: &BeaconChain<T>,
|
||||
parent_slot: Slot,
|
||||
block: BeaconBlockRef<'_, T::EthSpec>,
|
||||
) -> Result<(), BlockError<T::EthSpec>> {
|
||||
// Reject any block that exceeds our limit on skipped slots.
|
||||
if let Some(max_skip_slots) = chain.config.import_max_skip_slots {
|
||||
if block.slot() > parent_slot + max_skip_slots {
|
||||
return Err(BlockError::TooManySkippedSlots {
|
||||
parent_slot,
|
||||
block_slot: block.slot(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns `Ok(())` if the block's slot is greater than the anchor block's slot (if any).
|
||||
fn check_block_against_anchor_slot<T: BeaconChainTypes>(
|
||||
block: BeaconBlockRef<'_, T::EthSpec>,
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::{
|
||||
};
|
||||
use eth1::Config as Eth1Config;
|
||||
use execution_layer::ExecutionLayer;
|
||||
use fork_choice::{CountUnrealized, ForkChoice, ResetPayloadStatuses};
|
||||
use fork_choice::{ForkChoice, ResetPayloadStatuses};
|
||||
use futures::channel::mpsc::Sender;
|
||||
use kzg::{Kzg, TrustedSetup};
|
||||
use operation_pool::{OperationPool, PersistedOperationPool};
|
||||
@@ -701,7 +701,6 @@ where
|
||||
store.clone(),
|
||||
Some(current_slot),
|
||||
&self.spec,
|
||||
CountUnrealized::True,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@ pub const FORK_CHOICE_LOOKAHEAD_FACTOR: u32 = 24;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
|
||||
pub struct ChainConfig {
|
||||
/// Maximum number of slots to skip when importing a consensus message (e.g., block,
|
||||
/// attestation, etc).
|
||||
/// Maximum number of slots to skip when importing an attestation.
|
||||
///
|
||||
/// If `None`, there is no limit.
|
||||
pub import_max_skip_slots: Option<u64>,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{BeaconForkChoiceStore, BeaconSnapshot};
|
||||
use fork_choice::{CountUnrealized, ForkChoice, PayloadVerificationStatus};
|
||||
use fork_choice::{ForkChoice, PayloadVerificationStatus};
|
||||
use itertools::process_results;
|
||||
use slog::{info, warn, Logger};
|
||||
use state_processing::state_advance::complete_state_advance;
|
||||
@@ -100,7 +100,6 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
|
||||
store: Arc<HotColdDB<E, Hot, Cold>>,
|
||||
current_slot: Option<Slot>,
|
||||
spec: &ChainSpec,
|
||||
count_unrealized_config: CountUnrealized,
|
||||
) -> Result<ForkChoice<BeaconForkChoiceStore<E, Hot, Cold>, E>, String> {
|
||||
// Fetch finalized block.
|
||||
let finalized_checkpoint = head_state.finalized_checkpoint();
|
||||
@@ -166,8 +165,7 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
|
||||
.map_err(|e| format!("Error loading blocks to replay for fork choice: {:?}", e))?;
|
||||
|
||||
let mut state = finalized_snapshot.beacon_state;
|
||||
let blocks_len = blocks.len();
|
||||
for (i, block) in blocks.into_iter().enumerate() {
|
||||
for block in blocks {
|
||||
complete_state_advance(&mut state, None, block.slot(), spec)
|
||||
.map_err(|e| format!("State advance failed: {:?}", e))?;
|
||||
|
||||
@@ -190,15 +188,6 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
|
||||
// This scenario is so rare that it seems OK to double-verify some blocks.
|
||||
let payload_verification_status = PayloadVerificationStatus::Optimistic;
|
||||
|
||||
// Because we are replaying a single chain of blocks, we only need to calculate unrealized
|
||||
// justification for the last block in the chain.
|
||||
let is_last_block = i + 1 == blocks_len;
|
||||
let count_unrealized = if is_last_block {
|
||||
count_unrealized_config
|
||||
} else {
|
||||
CountUnrealized::False
|
||||
};
|
||||
|
||||
fork_choice
|
||||
.on_block(
|
||||
block.slot(),
|
||||
@@ -209,7 +198,6 @@ pub fn reset_fork_choice_to_finalization<E: EthSpec, Hot: ItemStore<E>, Cold: It
|
||||
&state,
|
||||
payload_verification_status,
|
||||
spec,
|
||||
count_unrealized,
|
||||
)
|
||||
.map_err(|e| format!("Error applying replayed block to fork choice: {:?}", e))?;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ pub mod validator_pubkey_cache;
|
||||
|
||||
pub use self::beacon_chain::{
|
||||
AttestationProcessingOutcome, AvailabilityProcessingStatus, BeaconChain, BeaconChainTypes,
|
||||
BeaconStore, ChainSegmentResult, CountUnrealized, ForkChoiceError, OverrideForkchoiceUpdate,
|
||||
BeaconStore, ChainSegmentResult, ForkChoiceError, OverrideForkchoiceUpdate,
|
||||
ProduceBlockVerification, StateSkipConfig, WhenSlotSkipped,
|
||||
INVALID_FINALIZED_MERGE_TRANSITION_BLOCK_SHUTDOWN_REASON,
|
||||
INVALID_JUSTIFIED_PAYLOAD_SHUTDOWN_REASON, MAXIMUM_GOSSIP_CLOCK_DISPARITY,
|
||||
|
||||
@@ -24,7 +24,6 @@ use execution_layer::{
|
||||
},
|
||||
ExecutionLayer,
|
||||
};
|
||||
use fork_choice::CountUnrealized;
|
||||
use futures::channel::mpsc::Receiver;
|
||||
pub use genesis::{interop_genesis_state_with_eth1, DEFAULT_ETH1_BLOCK_HASH};
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
@@ -1758,12 +1757,7 @@ where
|
||||
self.set_current_slot(slot);
|
||||
let block_hash: SignedBeaconBlockHash = self
|
||||
.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
block.into(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_block(block_root, block.into(), NotifyExecutionLayer::Yes)
|
||||
.await?
|
||||
.try_into()
|
||||
.unwrap();
|
||||
@@ -1781,7 +1775,6 @@ where
|
||||
.process_block(
|
||||
wrapped_block.canonical_root(),
|
||||
wrapped_block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await?
|
||||
|
||||
@@ -5,8 +5,9 @@ use beacon_chain::{
|
||||
blob_verification::AsBlock,
|
||||
test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType},
|
||||
};
|
||||
use beacon_chain::{BeaconSnapshot, BlockError, ChainSegmentResult, NotifyExecutionLayer};
|
||||
use fork_choice::CountUnrealized;
|
||||
use beacon_chain::{
|
||||
BeaconSnapshot, BlockError, ChainSegmentResult, IntoExecutionPendingBlock, NotifyExecutionLayer,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use logging::test_logger;
|
||||
use slasher::{Config as SlasherConfig, Slasher};
|
||||
@@ -153,18 +154,14 @@ async fn chain_segment_full_segment() {
|
||||
// Sneak in a little check to ensure we can process empty chain segments.
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(vec![], CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(vec![], NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.expect("should import empty chain segment");
|
||||
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
blocks.clone(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(blocks.clone(), NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.expect("should import chain segment");
|
||||
@@ -196,11 +193,7 @@ async fn chain_segment_varying_chunk_size() {
|
||||
for chunk in blocks.chunks(*chunk_size) {
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
chunk.to_vec(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(chunk.to_vec(), NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.unwrap_or_else(|_| panic!("should import chain segment of len {}", chunk_size));
|
||||
@@ -239,7 +232,7 @@ async fn chain_segment_non_linear_parent_roots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearParentRoots)
|
||||
@@ -263,7 +256,7 @@ async fn chain_segment_non_linear_parent_roots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearParentRoots)
|
||||
@@ -297,7 +290,7 @@ async fn chain_segment_non_linear_slots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearSlots)
|
||||
@@ -321,7 +314,7 @@ async fn chain_segment_non_linear_slots() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::NonLinearSlots)
|
||||
@@ -347,7 +340,7 @@ async fn assert_invalid_signature(
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::InvalidSignature)
|
||||
@@ -369,11 +362,7 @@ async fn assert_invalid_signature(
|
||||
// imported prior to this test.
|
||||
let _ = harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
ancestor_blocks,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(ancestor_blocks, NotifyExecutionLayer::Yes)
|
||||
.await;
|
||||
harness.chain.recompute_head_at_current_slot().await;
|
||||
|
||||
@@ -382,7 +371,6 @@ async fn assert_invalid_signature(
|
||||
.process_block(
|
||||
snapshots[block_index].beacon_block.canonical_root(),
|
||||
snapshots[block_index].beacon_block.clone(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await;
|
||||
@@ -435,11 +423,7 @@ async fn invalid_signature_gossip_block() {
|
||||
.collect();
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
ancestor_blocks,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(ancestor_blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error()
|
||||
.expect("should import all blocks prior to the one being tested");
|
||||
@@ -451,7 +435,6 @@ async fn invalid_signature_gossip_block() {
|
||||
.process_block(
|
||||
signed_block.canonical_root(),
|
||||
Arc::new(signed_block),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await,
|
||||
@@ -486,7 +469,7 @@ async fn invalid_signature_block_proposal() {
|
||||
matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::InvalidSignature)
|
||||
@@ -684,7 +667,7 @@ async fn invalid_signature_deposit() {
|
||||
!matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(blocks, CountUnrealized::True, NotifyExecutionLayer::Yes)
|
||||
.process_chain_segment(blocks, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.into_block_error(),
|
||||
Err(BlockError::InvalidSignature)
|
||||
@@ -764,7 +747,6 @@ async fn block_gossip_verification() {
|
||||
.process_block(
|
||||
gossip_verified.block_root,
|
||||
gossip_verified,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1039,7 +1021,6 @@ async fn verify_block_for_gossip_slashing_detection() {
|
||||
.process_block(
|
||||
verified_block.block_root,
|
||||
verified_block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1079,7 +1060,6 @@ async fn verify_block_for_gossip_doppelganger_detection() {
|
||||
.process_block(
|
||||
verified_block.block_root,
|
||||
verified_block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1227,7 +1207,6 @@ async fn add_base_block_to_altair_chain() {
|
||||
.process_block(
|
||||
base_block.canonical_root(),
|
||||
Arc::new(base_block.clone()),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1243,11 +1222,7 @@ async fn add_base_block_to_altair_chain() {
|
||||
assert!(matches!(
|
||||
harness
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
vec![Arc::new(base_block).into()],
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_chain_segment(vec![Arc::new(base_block).into()], NotifyExecutionLayer::Yes,)
|
||||
.await,
|
||||
ChainSegmentResult::Failed {
|
||||
imported_blocks: 0,
|
||||
@@ -1366,7 +1341,6 @@ async fn add_altair_block_to_base_chain() {
|
||||
.process_block(
|
||||
altair_block.canonical_root(),
|
||||
Arc::new(altair_block.clone()),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1384,7 +1358,6 @@ async fn add_altair_block_to_base_chain() {
|
||||
.chain
|
||||
.process_chain_segment(
|
||||
vec![Arc::new(altair_block).into()],
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes
|
||||
)
|
||||
.await,
|
||||
@@ -1397,3 +1370,100 @@ async fn add_altair_block_to_base_chain() {
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn import_duplicate_block_unrealized_justification() {
|
||||
let spec = MainnetEthSpec::default_spec();
|
||||
|
||||
let harness = BeaconChainHarness::builder(MainnetEthSpec)
|
||||
.spec(spec)
|
||||
.keypairs(KEYPAIRS[..].to_vec())
|
||||
.fresh_ephemeral_store()
|
||||
.mock_execution_layer()
|
||||
.build();
|
||||
let chain = &harness.chain;
|
||||
|
||||
// Move out of the genesis slot.
|
||||
harness.advance_slot();
|
||||
|
||||
// Build the chain out to the first justification opportunity 2/3rds of the way through epoch 2.
|
||||
let num_slots = E::slots_per_epoch() as usize * 8 / 3;
|
||||
harness
|
||||
.extend_chain(
|
||||
num_slots,
|
||||
BlockStrategy::OnCanonicalHead,
|
||||
AttestationStrategy::AllValidators,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Move into the next empty slot.
|
||||
harness.advance_slot();
|
||||
|
||||
// The store's justified checkpoint must still be at epoch 0, while unrealized justification
|
||||
// must be at epoch 1.
|
||||
let fc = chain.canonical_head.fork_choice_read_lock();
|
||||
assert_eq!(fc.justified_checkpoint().epoch, 0);
|
||||
assert_eq!(fc.unrealized_justified_checkpoint().epoch, 1);
|
||||
drop(fc);
|
||||
|
||||
// Produce a block to justify epoch 2.
|
||||
let state = harness.get_current_state();
|
||||
let slot = harness.get_current_slot();
|
||||
let (block, _) = harness.make_block(state.clone(), slot).await;
|
||||
let block = Arc::new(block);
|
||||
let block_root = block.canonical_root();
|
||||
|
||||
// Create two verified variants of the block, representing the same block being processed in
|
||||
// parallel.
|
||||
let notify_execution_layer = NotifyExecutionLayer::Yes;
|
||||
let verified_block1 = block
|
||||
.clone()
|
||||
.into_execution_pending_block(block_root, &chain, notify_execution_layer)
|
||||
.unwrap();
|
||||
let verified_block2 = block
|
||||
.into_execution_pending_block(block_root, &chain, notify_execution_layer)
|
||||
.unwrap();
|
||||
|
||||
// Import the first block, simulating a block processed via a finalized chain segment.
|
||||
chain
|
||||
.clone()
|
||||
.import_execution_pending_block(verified_block1)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Unrealized justification should NOT have updated.
|
||||
let fc = chain.canonical_head.fork_choice_read_lock();
|
||||
assert_eq!(fc.justified_checkpoint().epoch, 0);
|
||||
let unrealized_justification = fc.unrealized_justified_checkpoint();
|
||||
assert_eq!(unrealized_justification.epoch, 2);
|
||||
|
||||
// The fork choice node for the block should have unrealized justification.
|
||||
let fc_block = fc.get_block(&block_root).unwrap();
|
||||
assert_eq!(
|
||||
fc_block.unrealized_justified_checkpoint,
|
||||
Some(unrealized_justification)
|
||||
);
|
||||
drop(fc);
|
||||
|
||||
// Import the second verified block, simulating a block processed via RPC.
|
||||
chain
|
||||
.clone()
|
||||
.import_execution_pending_block(verified_block2)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Unrealized justification should still be updated.
|
||||
let fc = chain.canonical_head.fork_choice_read_lock();
|
||||
assert_eq!(fc.justified_checkpoint().epoch, 0);
|
||||
assert_eq!(
|
||||
fc.unrealized_justified_checkpoint(),
|
||||
unrealized_justification
|
||||
);
|
||||
|
||||
// The fork choice node for the block should still have the unrealized justified checkpoint.
|
||||
let fc_block = fc.get_block(&block_root).unwrap();
|
||||
assert_eq!(
|
||||
fc_block.unrealized_justified_checkpoint,
|
||||
Some(unrealized_justification)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ use execution_layer::{
|
||||
test_utils::ExecutionBlockGenerator,
|
||||
ExecutionLayer, ForkchoiceState, PayloadAttributes,
|
||||
};
|
||||
use fork_choice::{
|
||||
CountUnrealized, Error as ForkChoiceError, InvalidationOperation, PayloadVerificationStatus,
|
||||
};
|
||||
use fork_choice::{Error as ForkChoiceError, InvalidationOperation, PayloadVerificationStatus};
|
||||
use logging::test_logger;
|
||||
use proto_array::{Error as ProtoArrayError, ExecutionStatus};
|
||||
use slot_clock::SlotClock;
|
||||
@@ -699,7 +697,6 @@ async fn invalidates_all_descendants() {
|
||||
.process_block(
|
||||
fork_block.canonical_root(),
|
||||
Arc::new(fork_block),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -799,7 +796,6 @@ async fn switches_heads() {
|
||||
.process_block(
|
||||
fork_block.canonical_root(),
|
||||
Arc::new(fork_block),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
@@ -1056,7 +1052,7 @@ async fn invalid_parent() {
|
||||
|
||||
// Ensure the block built atop an invalid payload is invalid for import.
|
||||
assert!(matches!(
|
||||
rig.harness.chain.process_block(block.canonical_root(), block.clone(), CountUnrealized::True, NotifyExecutionLayer::Yes).await,
|
||||
rig.harness.chain.process_block(block.canonical_root(), block.clone(), NotifyExecutionLayer::Yes).await,
|
||||
Err(BlockError::ParentExecutionPayloadInvalid { parent_root: invalid_root })
|
||||
if invalid_root == parent_root
|
||||
));
|
||||
@@ -1071,7 +1067,7 @@ async fn invalid_parent() {
|
||||
&state,
|
||||
PayloadVerificationStatus::Optimistic,
|
||||
&rig.harness.chain.spec,
|
||||
CountUnrealized::True,
|
||||
|
||||
),
|
||||
Err(ForkChoiceError::ProtoArrayStringError(message))
|
||||
if message.contains(&format!(
|
||||
@@ -1342,12 +1338,7 @@ async fn build_optimistic_chain(
|
||||
for block in blocks {
|
||||
rig.harness
|
||||
.chain
|
||||
.process_block(
|
||||
block.canonical_root(),
|
||||
block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_block(block.canonical_root(), block, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
@@ -1906,7 +1897,6 @@ async fn recover_from_invalid_head_by_importing_blocks() {
|
||||
.process_block(
|
||||
fork_block.canonical_root(),
|
||||
fork_block.clone(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -13,7 +13,6 @@ use beacon_chain::{
|
||||
ChainConfig, NotifyExecutionLayer, ServerSentEventHandler, WhenSlotSkipped,
|
||||
};
|
||||
use eth2_network_config::TRUSTED_SETUP;
|
||||
use fork_choice::CountUnrealized;
|
||||
use kzg::TrustedSetup;
|
||||
use lazy_static::lazy_static;
|
||||
use logging::test_logger;
|
||||
@@ -2165,7 +2164,6 @@ async fn weak_subjectivity_sync() {
|
||||
.process_block(
|
||||
full_block.canonical_root(),
|
||||
Arc::new(full_block),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -8,7 +8,6 @@ use beacon_chain::{
|
||||
},
|
||||
BeaconChain, NotifyExecutionLayer, StateSkipConfig, WhenSlotSkipped,
|
||||
};
|
||||
use fork_choice::CountUnrealized;
|
||||
use lazy_static::lazy_static;
|
||||
use operation_pool::PersistedOperationPool;
|
||||
use state_processing::{
|
||||
@@ -686,7 +685,6 @@ async fn run_skip_slot_test(skip_slots: u64) {
|
||||
.process_block(
|
||||
harness_a.chain.head_snapshot().beacon_block_root,
|
||||
harness_a.chain.head_snapshot().beacon_block.clone(),
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::metrics;
|
||||
use beacon_chain::blob_verification::{AsBlock, BlockWrapper};
|
||||
use beacon_chain::validator_monitor::{get_block_delay_ms, timestamp_now};
|
||||
use beacon_chain::{AvailabilityProcessingStatus, NotifyExecutionLayer};
|
||||
use beacon_chain::{BeaconChain, BeaconChainTypes, BlockError, CountUnrealized};
|
||||
use beacon_chain::{BeaconChain, BeaconChainTypes, BlockError};
|
||||
use eth2::types::SignedBlockContents;
|
||||
use execution_layer::ProvenancedPayload;
|
||||
use lighthouse_network::PubsubMessage;
|
||||
@@ -94,12 +94,7 @@ pub async fn publish_block<T: BeaconChainTypes>(
|
||||
let slot = block_clone.message().slot();
|
||||
let proposer_index = block_clone.message().proposer_index();
|
||||
match chain
|
||||
.process_block(
|
||||
block_root,
|
||||
wrapped_block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_block(block_root, wrapped_block, NotifyExecutionLayer::Yes)
|
||||
.await
|
||||
{
|
||||
Ok(AvailabilityProcessingStatus::Imported(root)) => {
|
||||
|
||||
@@ -5,7 +5,7 @@ authors = ["Sigma Prime <contact@sigmaprime.io>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
discv5 = { version = "0.2.2", features = ["libp2p"] }
|
||||
discv5 = { version = "0.3.0", features = ["libp2p"]}
|
||||
unsigned-varint = { version = "0.6.0", features = ["codec"] }
|
||||
types = { path = "../../consensus/types" }
|
||||
ssz_types = "0.5.0"
|
||||
@@ -60,4 +60,4 @@ quickcheck = "0.9.2"
|
||||
quickcheck_macros = "0.9.1"
|
||||
|
||||
[features]
|
||||
libp2p-websocket = []
|
||||
libp2p-websocket = []
|
||||
@@ -163,7 +163,7 @@ impl Config {
|
||||
udp_port,
|
||||
tcp_port,
|
||||
});
|
||||
self.discv5_config.ip_mode = discv5::IpMode::Ip4;
|
||||
self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), udp_port);
|
||||
self.discv5_config.table_filter = |enr| enr.ip4().as_ref().map_or(false, is_global_ipv4)
|
||||
}
|
||||
|
||||
@@ -176,9 +176,8 @@ impl Config {
|
||||
udp_port,
|
||||
tcp_port,
|
||||
});
|
||||
self.discv5_config.ip_mode = discv5::IpMode::Ip6 {
|
||||
enable_mapped_addresses: false,
|
||||
};
|
||||
|
||||
self.discv5_config.listen_config = discv5::ListenConfig::from_ip(addr.into(), udp_port);
|
||||
self.discv5_config.table_filter = |enr| enr.ip6().as_ref().map_or(false, is_global_ipv6)
|
||||
}
|
||||
|
||||
@@ -206,10 +205,10 @@ impl Config {
|
||||
tcp_port: tcp6_port,
|
||||
},
|
||||
);
|
||||
self.discv5_config.listen_config = discv5::ListenConfig::default()
|
||||
.with_ipv4(v4_addr, udp4_port)
|
||||
.with_ipv6(v6_addr, udp6_port);
|
||||
|
||||
self.discv5_config.ip_mode = discv5::IpMode::Ip6 {
|
||||
enable_mapped_addresses: true,
|
||||
};
|
||||
self.discv5_config.table_filter = |enr| match (&enr.ip4(), &enr.ip6()) {
|
||||
(None, None) => false,
|
||||
(None, Some(ip6)) => is_global_ipv6(ip6),
|
||||
@@ -279,9 +278,17 @@ impl Default for Config {
|
||||
.build()
|
||||
.expect("The total rate limit has been specified"),
|
||||
);
|
||||
let listen_addresses = ListenAddress::V4(ListenAddr {
|
||||
addr: Ipv4Addr::UNSPECIFIED,
|
||||
udp_port: 9000,
|
||||
tcp_port: 9000,
|
||||
});
|
||||
|
||||
let discv5_listen_config =
|
||||
discv5::ListenConfig::from_ip(Ipv4Addr::UNSPECIFIED.into(), 9000);
|
||||
|
||||
// discv5 configuration
|
||||
let discv5_config = Discv5ConfigBuilder::new()
|
||||
let discv5_config = Discv5ConfigBuilder::new(discv5_listen_config)
|
||||
.enable_packet_filter()
|
||||
.session_cache_capacity(5000)
|
||||
.request_timeout(Duration::from_secs(1))
|
||||
@@ -304,12 +311,9 @@ impl Default for Config {
|
||||
// NOTE: Some of these get overridden by the corresponding CLI default values.
|
||||
Config {
|
||||
network_dir,
|
||||
listen_addresses: ListenAddress::V4(ListenAddr {
|
||||
addr: Ipv4Addr::UNSPECIFIED,
|
||||
udp_port: 9000,
|
||||
tcp_port: 9000,
|
||||
}),
|
||||
listen_addresses,
|
||||
enr_address: (None, None),
|
||||
|
||||
enr_udp4_port: None,
|
||||
enr_tcp4_port: None,
|
||||
enr_udp6_port: None,
|
||||
|
||||
@@ -213,13 +213,17 @@ pub fn build_enr<T: EthSpec>(
|
||||
fn compare_enr(local_enr: &Enr, disk_enr: &Enr) -> bool {
|
||||
// take preference over disk_enr address if one is not specified
|
||||
(local_enr.ip4().is_none() || local_enr.ip4() == disk_enr.ip4())
|
||||
&&
|
||||
(local_enr.ip6().is_none() || local_enr.ip6() == disk_enr.ip6())
|
||||
// tcp ports must match
|
||||
&& local_enr.tcp4() == disk_enr.tcp4()
|
||||
&& local_enr.tcp6() == disk_enr.tcp6()
|
||||
// must match on the same fork
|
||||
&& local_enr.get(ETH2_ENR_KEY) == disk_enr.get(ETH2_ENR_KEY)
|
||||
// take preference over disk udp port if one is not specified
|
||||
&& (local_enr.udp4().is_none() || local_enr.udp4() == disk_enr.udp4())
|
||||
// we need the ATTESTATION_BITFIELD_ENR_KEY and SYNC_COMMITTEE_BITFIELD_ENR_KEY key to match,
|
||||
&& (local_enr.udp6().is_none() || local_enr.udp6() == disk_enr.udp6())
|
||||
// we need the ATTESTATION_BITFIELD_ENR_KEY and SYNC_COMMITTEE_BITFIELD_ENR_KEY key to match,
|
||||
// otherwise we use a new ENR. This will likely only be true for non-validating nodes
|
||||
&& local_enr.get(ATTESTATION_BITFIELD_ENR_KEY) == disk_enr.get(ATTESTATION_BITFIELD_ENR_KEY)
|
||||
&& local_enr.get(SYNC_COMMITTEE_BITFIELD_ENR_KEY) == disk_enr.get(SYNC_COMMITTEE_BITFIELD_ENR_KEY)
|
||||
|
||||
@@ -198,7 +198,7 @@ impl CombinedKeyPublicExt for CombinedPublicKey {
|
||||
fn as_peer_id(&self) -> PeerId {
|
||||
match self {
|
||||
Self::Secp256k1(pk) => {
|
||||
let pk_bytes = pk.to_bytes();
|
||||
let pk_bytes = pk.to_sec1_bytes();
|
||||
let libp2p_pk = libp2p::core::PublicKey::Secp256k1(
|
||||
libp2p::core::identity::secp256k1::PublicKey::decode(&pk_bytes)
|
||||
.expect("valid public key"),
|
||||
@@ -222,14 +222,16 @@ impl CombinedKeyExt for CombinedKey {
|
||||
match key {
|
||||
Keypair::Secp256k1(key) => {
|
||||
let secret =
|
||||
discv5::enr::k256::ecdsa::SigningKey::from_bytes(&key.secret().to_bytes())
|
||||
discv5::enr::k256::ecdsa::SigningKey::from_slice(&key.secret().to_bytes())
|
||||
.expect("libp2p key must be valid");
|
||||
Ok(CombinedKey::Secp256k1(secret))
|
||||
}
|
||||
Keypair::Ed25519(key) => {
|
||||
let ed_keypair =
|
||||
discv5::enr::ed25519_dalek::SecretKey::from_bytes(&key.encode()[..32])
|
||||
.expect("libp2p key must be valid");
|
||||
let ed_keypair = discv5::enr::ed25519_dalek::SigningKey::from_bytes(
|
||||
&(key.encode()[..32])
|
||||
.try_into()
|
||||
.expect("libp2p key must be valid"),
|
||||
);
|
||||
Ok(CombinedKey::from(ed_keypair))
|
||||
}
|
||||
Keypair::Ecdsa(_) => Err("Ecdsa keypairs not supported"),
|
||||
@@ -281,7 +283,7 @@ mod tests {
|
||||
fn test_secp256k1_peer_id_conversion() {
|
||||
let sk_hex = "df94a73d528434ce2309abb19c16aedb535322797dbd59c157b1e04095900f48";
|
||||
let sk_bytes = hex::decode(sk_hex).unwrap();
|
||||
let secret_key = discv5::enr::k256::ecdsa::SigningKey::from_bytes(&sk_bytes).unwrap();
|
||||
let secret_key = discv5::enr::k256::ecdsa::SigningKey::from_slice(&sk_bytes).unwrap();
|
||||
|
||||
let libp2p_sk = libp2p::identity::secp256k1::SecretKey::from_bytes(sk_bytes).unwrap();
|
||||
let secp256k1_kp: libp2p::identity::secp256k1::Keypair = libp2p_sk.into();
|
||||
@@ -300,16 +302,18 @@ mod tests {
|
||||
fn test_ed25519_peer_conversion() {
|
||||
let sk_hex = "4dea8a5072119927e9d243a7d953f2f4bc95b70f110978e2f9bc7a9000e4b261";
|
||||
let sk_bytes = hex::decode(sk_hex).unwrap();
|
||||
let secret = discv5::enr::ed25519_dalek::SecretKey::from_bytes(&sk_bytes).unwrap();
|
||||
let public = discv5::enr::ed25519_dalek::PublicKey::from(&secret);
|
||||
let keypair = discv5::enr::ed25519_dalek::Keypair { secret, public };
|
||||
let secret_key = discv5::enr::ed25519_dalek::SigningKey::from_bytes(
|
||||
&sk_bytes.clone().try_into().unwrap(),
|
||||
);
|
||||
|
||||
let libp2p_sk = libp2p::identity::ed25519::SecretKey::from_bytes(sk_bytes).unwrap();
|
||||
let ed25519_kp: libp2p::identity::ed25519::Keypair = libp2p_sk.into();
|
||||
let libp2p_kp = Keypair::Ed25519(ed25519_kp);
|
||||
let secp256k1_kp: libp2p::identity::ed25519::Keypair = libp2p_sk.into();
|
||||
let libp2p_kp = Keypair::Ed25519(secp256k1_kp);
|
||||
let peer_id = libp2p_kp.public().to_peer_id();
|
||||
|
||||
let enr = discv5::enr::EnrBuilder::new("v4").build(&keypair).unwrap();
|
||||
let enr = discv5::enr::EnrBuilder::new("v4")
|
||||
.build(&secret_key)
|
||||
.unwrap();
|
||||
let node_id = peer_id_to_node_id(&peer_id).unwrap();
|
||||
|
||||
assert_eq!(enr.node_id(), node_id);
|
||||
|
||||
@@ -209,13 +209,6 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
||||
info!(log, "ENR Initialised"; "enr" => local_enr.to_base64(), "seq" => local_enr.seq(), "id"=> %local_enr.node_id(),
|
||||
"ip4" => ?local_enr.ip4(), "udp4"=> ?local_enr.udp4(), "tcp4" => ?local_enr.tcp4(), "tcp6" => ?local_enr.tcp6(), "udp6" => ?local_enr.udp6()
|
||||
);
|
||||
let listen_socket = match config.listen_addrs() {
|
||||
crate::listen_addr::ListenAddress::V4(v4_addr) => v4_addr.udp_socket_addr(),
|
||||
crate::listen_addr::ListenAddress::V6(v6_addr) => v6_addr.udp_socket_addr(),
|
||||
crate::listen_addr::ListenAddress::DualStack(_v4_addr, v6_addr) => {
|
||||
v6_addr.udp_socket_addr()
|
||||
}
|
||||
};
|
||||
|
||||
// convert the keypair into an ENR key
|
||||
let enr_key: CombinedKey = CombinedKey::from_libp2p(local_key)?;
|
||||
@@ -251,10 +244,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
||||
|
||||
// Start the discv5 service and obtain an event stream
|
||||
let event_stream = if !config.disable_discovery {
|
||||
discv5
|
||||
.start(listen_socket)
|
||||
.map_err(|e| e.to_string())
|
||||
.await?;
|
||||
discv5.start().map_err(|e| e.to_string()).await?;
|
||||
debug!(log, "Discovery service started");
|
||||
EventStream::Awaiting(Box::pin(discv5.event_stream()))
|
||||
} else {
|
||||
@@ -413,7 +403,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
||||
/// If the external address needs to be modified, use `update_enr_udp_socket.
|
||||
pub fn update_enr_tcp_port(&mut self, port: u16) -> Result<(), String> {
|
||||
self.discv5
|
||||
.enr_insert("tcp", &port.to_be_bytes())
|
||||
.enr_insert("tcp", &port)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
// replace the global version
|
||||
@@ -428,29 +418,12 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
||||
/// This is with caution. Discovery should automatically maintain this. This should only be
|
||||
/// used when automatic discovery is disabled.
|
||||
pub fn update_enr_udp_socket(&mut self, socket_addr: SocketAddr) -> Result<(), String> {
|
||||
match socket_addr {
|
||||
SocketAddr::V4(socket) => {
|
||||
self.discv5
|
||||
.enr_insert("ip", &socket.ip().octets())
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
self.discv5
|
||||
.enr_insert("udp", &socket.port().to_be_bytes())
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
}
|
||||
SocketAddr::V6(socket) => {
|
||||
self.discv5
|
||||
.enr_insert("ip6", &socket.ip().octets())
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
self.discv5
|
||||
.enr_insert("udp6", &socket.port().to_be_bytes())
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
}
|
||||
const IS_TCP: bool = false;
|
||||
if self.discv5.update_local_enr_socket(socket_addr, IS_TCP) {
|
||||
// persist modified enr to disk
|
||||
enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log);
|
||||
}
|
||||
|
||||
// replace the global version
|
||||
*self.network_globals.local_enr.write() = self.discv5.local_enr();
|
||||
// persist modified enr to disk
|
||||
enr::save_enr_to_disk(Path::new(&self.enr_dir), &self.local_enr(), &self.log);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -217,8 +217,7 @@ mod tests {
|
||||
let mut buf = BytesMut::new();
|
||||
buf.extend_from_slice(&message);
|
||||
|
||||
let snappy_protocol_id =
|
||||
ProtocolId::new(Protocol::Status, Version::V1, Encoding::SSZSnappy);
|
||||
let snappy_protocol_id = ProtocolId::new(SupportedProtocol::StatusV1, Encoding::SSZSnappy);
|
||||
|
||||
let fork_context = Arc::new(fork_context(ForkName::Base));
|
||||
let mut snappy_outbound_codec = SSZSnappyOutboundCodec::<Spec>::new(
|
||||
@@ -252,8 +251,7 @@ mod tests {
|
||||
// Insert length-prefix
|
||||
uvi_codec.encode(len, &mut dst).unwrap();
|
||||
|
||||
let snappy_protocol_id =
|
||||
ProtocolId::new(Protocol::Status, Version::V1, Encoding::SSZSnappy);
|
||||
let snappy_protocol_id = ProtocolId::new(SupportedProtocol::StatusV1, Encoding::SSZSnappy);
|
||||
|
||||
let fork_context = Arc::new(fork_context(ForkName::Base));
|
||||
let mut snappy_outbound_codec = SSZSnappyOutboundCodec::<Spec>::new(
|
||||
@@ -280,8 +278,7 @@ mod tests {
|
||||
dst
|
||||
}
|
||||
|
||||
let protocol_id =
|
||||
ProtocolId::new(Protocol::BlocksByRange, Version::V1, Encoding::SSZSnappy);
|
||||
let protocol_id = ProtocolId::new(SupportedProtocol::BlocksByRangeV1, Encoding::SSZSnappy);
|
||||
|
||||
// Response limits
|
||||
let fork_context = Arc::new(fork_context(ForkName::Base));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ use super::protocol::{max_rpc_size, InboundRequest, Protocol, RPCError, RPCProto
|
||||
use super::{RPCReceived, RPCSend, ReqId};
|
||||
use crate::rpc::outbound::{OutboundFramed, OutboundRequest};
|
||||
use crate::rpc::protocol::InboundFramed;
|
||||
use crate::rpc::ResponseTermination;
|
||||
use fnv::FnvHashMap;
|
||||
use futures::prelude::*;
|
||||
use futures::{Sink, SinkExt};
|
||||
@@ -245,7 +246,7 @@ where
|
||||
while let Some((id, req)) = self.dial_queue.pop() {
|
||||
self.events_out.push(Err(HandlerErr::Outbound {
|
||||
error: RPCError::Disconnected,
|
||||
proto: req.protocol(),
|
||||
proto: req.versioned_protocol().protocol(),
|
||||
id,
|
||||
}));
|
||||
}
|
||||
@@ -269,7 +270,7 @@ where
|
||||
}
|
||||
_ => self.events_out.push(Err(HandlerErr::Outbound {
|
||||
error: RPCError::Disconnected,
|
||||
proto: req.protocol(),
|
||||
proto: req.versioned_protocol().protocol(),
|
||||
id,
|
||||
})),
|
||||
}
|
||||
@@ -334,7 +335,7 @@ where
|
||||
) {
|
||||
self.dial_negotiated -= 1;
|
||||
let (id, request) = request_info;
|
||||
let proto = request.protocol();
|
||||
let proto = request.versioned_protocol().protocol();
|
||||
|
||||
// accept outbound connections only if the handler is not deactivated
|
||||
if matches!(self.state, HandlerState::Deactivated) {
|
||||
@@ -414,7 +415,7 @@ where
|
||||
128,
|
||||
) as usize),
|
||||
delay_key: Some(delay_key),
|
||||
protocol: req.protocol(),
|
||||
protocol: req.versioned_protocol().protocol(),
|
||||
request_start_time: Instant::now(),
|
||||
remaining_chunks: expected_responses,
|
||||
},
|
||||
@@ -422,7 +423,7 @@ where
|
||||
} else {
|
||||
self.events_out.push(Err(HandlerErr::Inbound {
|
||||
id: self.current_inbound_substream_id,
|
||||
proto: req.protocol(),
|
||||
proto: req.versioned_protocol().protocol(),
|
||||
error: RPCError::HandlerRejected,
|
||||
}));
|
||||
return self.shutdown(None);
|
||||
@@ -498,7 +499,7 @@ where
|
||||
};
|
||||
self.events_out.push(Err(HandlerErr::Outbound {
|
||||
error,
|
||||
proto: req.protocol(),
|
||||
proto: req.versioned_protocol().protocol(),
|
||||
id,
|
||||
}));
|
||||
}
|
||||
@@ -895,7 +896,7 @@ where
|
||||
// else we return an error, stream should not have closed early.
|
||||
let outbound_err = HandlerErr::Outbound {
|
||||
id: request_id,
|
||||
proto: request.protocol(),
|
||||
proto: request.versioned_protocol().protocol(),
|
||||
error: RPCError::IncompleteStream,
|
||||
};
|
||||
return Poll::Ready(ConnectionHandlerEvent::Custom(Err(outbound_err)));
|
||||
@@ -933,8 +934,13 @@ where
|
||||
// continue sending responses beyond what we would expect. Here
|
||||
// we simply terminate the stream and report a stream
|
||||
// termination to the application
|
||||
let termination = match protocol {
|
||||
Protocol::BlocksByRange => Some(ResponseTermination::BlocksByRange),
|
||||
Protocol::BlocksByRoot => Some(ResponseTermination::BlocksByRoot),
|
||||
_ => None, // all other protocols are do not have multiple responses and we do not inform the user, we simply drop the stream.
|
||||
};
|
||||
|
||||
if let Some(termination) = protocol.terminator() {
|
||||
if let Some(termination) = termination {
|
||||
return Poll::Ready(ConnectionHandlerEvent::Custom(Ok(
|
||||
RPCReceived::EndOfStream(request_id, termination),
|
||||
)));
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
use crate::types::{EnrAttestationBitfield, EnrSyncCommitteeBitfield};
|
||||
use regex::bytes::Regex;
|
||||
use serde::Serialize;
|
||||
use ssz::Encode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use ssz_types::{
|
||||
typenum::{U1024, U256, U768},
|
||||
VariableList,
|
||||
};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use strum::IntoStaticStr;
|
||||
@@ -96,6 +98,30 @@ pub struct Ping {
|
||||
pub data: u64,
|
||||
}
|
||||
|
||||
/// The METADATA request structure.
|
||||
#[superstruct(
|
||||
variants(V1, V2),
|
||||
variant_attributes(derive(Clone, Debug, PartialEq, Serialize),)
|
||||
)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MetadataRequest<T: EthSpec> {
|
||||
_phantom_data: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> MetadataRequest<T> {
|
||||
pub fn new_v1() -> Self {
|
||||
Self::V1(MetadataRequestV1 {
|
||||
_phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_v2() -> Self {
|
||||
Self::V2(MetadataRequestV2 {
|
||||
_phantom_data: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The METADATA response structure.
|
||||
#[superstruct(
|
||||
variants(V1, V2),
|
||||
@@ -104,9 +130,8 @@ pub struct Ping {
|
||||
serde(bound = "T: EthSpec", deny_unknown_fields),
|
||||
)
|
||||
)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Encode)]
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
#[ssz(enum_behaviour = "transparent")]
|
||||
pub struct MetaData<T: EthSpec> {
|
||||
/// A sequential counter indicating when data gets modified.
|
||||
pub seq_number: u64,
|
||||
@@ -117,6 +142,38 @@ pub struct MetaData<T: EthSpec> {
|
||||
pub syncnets: EnrSyncCommitteeBitfield<T>,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> MetaData<T> {
|
||||
/// Returns a V1 MetaData response from self.
|
||||
pub fn metadata_v1(&self) -> Self {
|
||||
match self {
|
||||
md @ MetaData::V1(_) => md.clone(),
|
||||
MetaData::V2(metadata) => MetaData::V1(MetaDataV1 {
|
||||
seq_number: metadata.seq_number,
|
||||
attnets: metadata.attnets.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a V2 MetaData response from self by filling unavailable fields with default.
|
||||
pub fn metadata_v2(&self) -> Self {
|
||||
match self {
|
||||
MetaData::V1(metadata) => MetaData::V2(MetaDataV2 {
|
||||
seq_number: metadata.seq_number,
|
||||
attnets: metadata.attnets.clone(),
|
||||
syncnets: Default::default(),
|
||||
}),
|
||||
md @ MetaData::V2(_) => md.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ssz_bytes(&self) -> Vec<u8> {
|
||||
match self {
|
||||
MetaData::V1(md) => md.as_ssz_bytes(),
|
||||
MetaData::V2(md) => md.as_ssz_bytes(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The reason given for a `Goodbye` message.
|
||||
///
|
||||
/// Note: any unknown `u64::into(n)` will resolve to `Goodbye::Unknown` for any unknown `n`,
|
||||
@@ -208,7 +265,11 @@ impl ssz::Decode for GoodbyeReason {
|
||||
}
|
||||
|
||||
/// Request a number of beacon block roots from a peer.
|
||||
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
|
||||
#[superstruct(
|
||||
variants(V1, V2),
|
||||
variant_attributes(derive(Encode, Decode, Clone, Debug, PartialEq))
|
||||
)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BlocksByRangeRequest {
|
||||
/// The starting slot to request blocks.
|
||||
pub start_slot: u64,
|
||||
@@ -217,6 +278,17 @@ pub struct BlocksByRangeRequest {
|
||||
pub count: u64,
|
||||
}
|
||||
|
||||
impl BlocksByRangeRequest {
|
||||
/// The default request is V2
|
||||
pub fn new(start_slot: u64, count: u64) -> Self {
|
||||
Self::V2(BlocksByRangeRequestV2 { start_slot, count })
|
||||
}
|
||||
|
||||
pub fn new_v1(start_slot: u64, count: u64) -> Self {
|
||||
Self::V1(BlocksByRangeRequestV1 { start_slot, count })
|
||||
}
|
||||
}
|
||||
|
||||
/// Request a number of beacon blobs from a peer.
|
||||
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
|
||||
pub struct BlobsByRangeRequest {
|
||||
@@ -228,7 +300,11 @@ pub struct BlobsByRangeRequest {
|
||||
}
|
||||
|
||||
/// Request a number of beacon block roots from a peer.
|
||||
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
|
||||
#[superstruct(
|
||||
variants(V1, V2),
|
||||
variant_attributes(derive(Encode, Decode, Clone, Debug, PartialEq))
|
||||
)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct OldBlocksByRangeRequest {
|
||||
/// The starting slot to request blocks.
|
||||
pub start_slot: u64,
|
||||
@@ -244,13 +320,43 @@ pub struct OldBlocksByRangeRequest {
|
||||
pub step: u64,
|
||||
}
|
||||
|
||||
impl OldBlocksByRangeRequest {
|
||||
/// The default request is V2
|
||||
pub fn new(start_slot: u64, count: u64, step: u64) -> Self {
|
||||
Self::V2(OldBlocksByRangeRequestV2 {
|
||||
start_slot,
|
||||
count,
|
||||
step,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_v1(start_slot: u64, count: u64, step: u64) -> Self {
|
||||
Self::V1(OldBlocksByRangeRequestV1 {
|
||||
start_slot,
|
||||
count,
|
||||
step,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Request a number of beacon block bodies from a peer.
|
||||
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
|
||||
#[superstruct(variants(V1, V2), variant_attributes(derive(Clone, Debug, PartialEq)))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BlocksByRootRequest {
|
||||
/// The list of beacon block bodies being requested.
|
||||
pub block_roots: VariableList<Hash256, MaxRequestBlocks>,
|
||||
}
|
||||
|
||||
impl BlocksByRootRequest {
|
||||
pub fn new(block_roots: VariableList<Hash256, MaxRequestBlocks>) -> Self {
|
||||
Self::V2(BlocksByRootRequestV2 { block_roots })
|
||||
}
|
||||
|
||||
pub fn new_v1(block_roots: VariableList<Hash256, MaxRequestBlocks>) -> Self {
|
||||
Self::V1(BlocksByRootRequestV1 { block_roots })
|
||||
}
|
||||
}
|
||||
|
||||
/// Request a number of beacon blocks and blobs from a peer.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct BlobsByRootRequest {
|
||||
@@ -492,7 +598,12 @@ impl std::fmt::Display for GoodbyeReason {
|
||||
|
||||
impl std::fmt::Display for BlocksByRangeRequest {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Start Slot: {}, Count: {}", self.start_slot, self.count)
|
||||
write!(
|
||||
f,
|
||||
"Start Slot: {}, Count: {}",
|
||||
self.start_slot(),
|
||||
self.count()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,7 +612,9 @@ impl std::fmt::Display for OldBlocksByRangeRequest {
|
||||
write!(
|
||||
f,
|
||||
"Start Slot: {}, Count: {}, Step: {}",
|
||||
self.start_slot, self.count, self.step
|
||||
self.start_slot(),
|
||||
self.count(),
|
||||
self.step()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ where
|
||||
}
|
||||
Err(RateLimitedErr::TooLarge) => {
|
||||
// we set the batch sizes, so this is a coding/config err for most protocols
|
||||
let protocol = req.protocol();
|
||||
let protocol = req.versioned_protocol().protocol();
|
||||
if matches!(protocol, Protocol::BlocksByRange) {
|
||||
debug!(self.log, "Blocks by range request will never be processed"; "request" => %req);
|
||||
} else {
|
||||
@@ -335,7 +335,7 @@ where
|
||||
serializer.emit_arguments("peer_id", &format_args!("{}", self.peer_id))?;
|
||||
let (msg_kind, protocol) = match &self.event {
|
||||
Ok(received) => match received {
|
||||
RPCReceived::Request(_, req) => ("request", req.protocol()),
|
||||
RPCReceived::Request(_, req) => ("request", req.versioned_protocol().protocol()),
|
||||
RPCReceived::Response(_, res) => ("response", res.protocol()),
|
||||
RPCReceived::EndOfStream(_, end) => (
|
||||
"end_of_stream",
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use super::methods::*;
|
||||
use super::protocol::Protocol;
|
||||
use super::protocol::ProtocolId;
|
||||
use super::protocol::SupportedProtocol;
|
||||
use super::RPCError;
|
||||
use crate::rpc::protocol::Encoding;
|
||||
use crate::rpc::protocol::Version;
|
||||
use crate::rpc::{
|
||||
codec::{base::BaseOutboundCodec, ssz_snappy::SSZSnappyOutboundCodec, OutboundCodec},
|
||||
methods::ResponseTermination,
|
||||
@@ -40,9 +37,8 @@ pub enum OutboundRequest<TSpec: EthSpec> {
|
||||
BlocksByRoot(BlocksByRootRequest),
|
||||
BlobsByRange(BlobsByRangeRequest),
|
||||
BlobsByRoot(BlobsByRootRequest),
|
||||
LightClientBootstrap(LightClientBootstrapRequest),
|
||||
Ping(Ping),
|
||||
MetaData(PhantomData<TSpec>),
|
||||
MetaData(MetadataRequest<TSpec>),
|
||||
}
|
||||
|
||||
impl<TSpec: EthSpec> UpgradeInfo for OutboundRequestContainer<TSpec> {
|
||||
@@ -61,46 +57,37 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
|
||||
match self {
|
||||
// add more protocols when versions/encodings are supported
|
||||
OutboundRequest::Status(_) => vec![ProtocolId::new(
|
||||
Protocol::Status,
|
||||
Version::V1,
|
||||
SupportedProtocol::StatusV1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
OutboundRequest::Goodbye(_) => vec![ProtocolId::new(
|
||||
Protocol::Goodbye,
|
||||
Version::V1,
|
||||
SupportedProtocol::GoodbyeV1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
OutboundRequest::BlocksByRange(_) => vec![
|
||||
ProtocolId::new(Protocol::BlocksByRange, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlocksByRange, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::BlocksByRangeV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::BlocksByRangeV1, Encoding::SSZSnappy),
|
||||
],
|
||||
OutboundRequest::BlocksByRoot(_) => vec![
|
||||
ProtocolId::new(Protocol::BlocksByRoot, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlocksByRoot, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::BlocksByRootV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::BlocksByRootV1, Encoding::SSZSnappy),
|
||||
],
|
||||
OutboundRequest::BlobsByRange(_) => vec![ProtocolId::new(
|
||||
Protocol::BlobsByRange,
|
||||
Version::V1,
|
||||
SupportedProtocol::BlobsByRangeV1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
OutboundRequest::BlobsByRoot(_) => vec![ProtocolId::new(
|
||||
Protocol::BlobsByRoot,
|
||||
Version::V1,
|
||||
SupportedProtocol::BlobsByRootV1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
OutboundRequest::Ping(_) => vec![ProtocolId::new(
|
||||
Protocol::Ping,
|
||||
Version::V1,
|
||||
SupportedProtocol::PingV1,
|
||||
Encoding::SSZSnappy,
|
||||
)],
|
||||
OutboundRequest::MetaData(_) => vec![
|
||||
ProtocolId::new(Protocol::MetaData, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::MetaData, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::MetaDataV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::MetaDataV1, Encoding::SSZSnappy),
|
||||
],
|
||||
// Note: This match arm is technically unreachable as we only respond to light client requests
|
||||
// that we generate from the beacon state.
|
||||
// We do not make light client rpc requests from the beacon node
|
||||
OutboundRequest::LightClientBootstrap(_) => vec![],
|
||||
}
|
||||
}
|
||||
/* These functions are used in the handler for stream management */
|
||||
@@ -110,28 +97,35 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
|
||||
match self {
|
||||
OutboundRequest::Status(_) => 1,
|
||||
OutboundRequest::Goodbye(_) => 0,
|
||||
OutboundRequest::BlocksByRange(req) => req.count,
|
||||
OutboundRequest::BlocksByRoot(req) => req.block_roots.len() as u64,
|
||||
OutboundRequest::BlocksByRange(req) => *req.count(),
|
||||
OutboundRequest::BlocksByRoot(req) => req.block_roots().len() as u64,
|
||||
OutboundRequest::BlobsByRange(req) => req.count * TSpec::max_blobs_per_block() as u64,
|
||||
OutboundRequest::BlobsByRoot(req) => req.blob_ids.len() as u64,
|
||||
OutboundRequest::Ping(_) => 1,
|
||||
OutboundRequest::MetaData(_) => 1,
|
||||
OutboundRequest::LightClientBootstrap(_) => 1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gives the corresponding `Protocol` to this request.
|
||||
pub fn protocol(&self) -> Protocol {
|
||||
/// Gives the corresponding `SupportedProtocol` to this request.
|
||||
pub fn versioned_protocol(&self) -> SupportedProtocol {
|
||||
match self {
|
||||
OutboundRequest::Status(_) => Protocol::Status,
|
||||
OutboundRequest::Goodbye(_) => Protocol::Goodbye,
|
||||
OutboundRequest::BlocksByRange(_) => Protocol::BlocksByRange,
|
||||
OutboundRequest::BlocksByRoot(_) => Protocol::BlocksByRoot,
|
||||
OutboundRequest::BlobsByRange(_) => Protocol::BlobsByRange,
|
||||
OutboundRequest::BlobsByRoot(_) => Protocol::BlobsByRoot,
|
||||
OutboundRequest::Ping(_) => Protocol::Ping,
|
||||
OutboundRequest::MetaData(_) => Protocol::MetaData,
|
||||
OutboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
|
||||
OutboundRequest::Status(_) => SupportedProtocol::StatusV1,
|
||||
OutboundRequest::Goodbye(_) => SupportedProtocol::GoodbyeV1,
|
||||
OutboundRequest::BlocksByRange(req) => match req {
|
||||
OldBlocksByRangeRequest::V1(_) => SupportedProtocol::BlocksByRangeV1,
|
||||
OldBlocksByRangeRequest::V2(_) => SupportedProtocol::BlocksByRangeV2,
|
||||
},
|
||||
OutboundRequest::BlocksByRoot(req) => match req {
|
||||
BlocksByRootRequest::V1(_) => SupportedProtocol::BlocksByRootV1,
|
||||
BlocksByRootRequest::V2(_) => SupportedProtocol::BlocksByRootV2,
|
||||
},
|
||||
OutboundRequest::BlobsByRange(_) => SupportedProtocol::BlobsByRangeV1,
|
||||
OutboundRequest::BlobsByRoot(_) => SupportedProtocol::BlobsByRootV1,
|
||||
OutboundRequest::Ping(_) => SupportedProtocol::PingV1,
|
||||
OutboundRequest::MetaData(req) => match req {
|
||||
MetadataRequest::V1(_) => SupportedProtocol::MetaDataV1,
|
||||
MetadataRequest::V2(_) => SupportedProtocol::MetaDataV2,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +139,6 @@ impl<TSpec: EthSpec> OutboundRequest<TSpec> {
|
||||
OutboundRequest::BlocksByRoot(_) => ResponseTermination::BlocksByRoot,
|
||||
OutboundRequest::BlobsByRange(_) => ResponseTermination::BlobsByRange,
|
||||
OutboundRequest::BlobsByRoot(_) => ResponseTermination::BlobsByRoot,
|
||||
OutboundRequest::LightClientBootstrap(_) => unreachable!(),
|
||||
OutboundRequest::Status(_) => unreachable!(),
|
||||
OutboundRequest::Goodbye(_) => unreachable!(),
|
||||
OutboundRequest::Ping(_) => unreachable!(),
|
||||
@@ -205,9 +198,6 @@ impl<TSpec: EthSpec> std::fmt::Display for OutboundRequest<TSpec> {
|
||||
OutboundRequest::BlobsByRoot(req) => write!(f, "Blobs by root: {:?}", req),
|
||||
OutboundRequest::Ping(ping) => write!(f, "Ping: {}", ping.data),
|
||||
OutboundRequest::MetaData(_) => write!(f, "MetaData request"),
|
||||
OutboundRequest::LightClientBootstrap(bootstrap) => {
|
||||
write!(f, "Lightclient Bootstrap: {}", bootstrap.root)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,35 +205,80 @@ pub enum Protocol {
|
||||
LightClientBootstrap,
|
||||
}
|
||||
|
||||
/// RPC Versions
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Version {
|
||||
/// Version 1 of RPC
|
||||
V1,
|
||||
/// Version 2 of RPC
|
||||
V2,
|
||||
}
|
||||
|
||||
/// RPC Encondings supported.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Encoding {
|
||||
SSZSnappy,
|
||||
}
|
||||
|
||||
impl Protocol {
|
||||
pub(crate) fn terminator(self) -> Option<ResponseTermination> {
|
||||
/// All valid protocol name and version combinations.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum SupportedProtocol {
|
||||
StatusV1,
|
||||
GoodbyeV1,
|
||||
BlocksByRangeV1,
|
||||
BlocksByRangeV2,
|
||||
BlocksByRootV1,
|
||||
BlocksByRootV2,
|
||||
BlobsByRangeV1,
|
||||
BlobsByRootV1,
|
||||
PingV1,
|
||||
MetaDataV1,
|
||||
MetaDataV2,
|
||||
LightClientBootstrapV1,
|
||||
}
|
||||
|
||||
impl SupportedProtocol {
|
||||
pub fn version_string(&self) -> &'static str {
|
||||
match self {
|
||||
Protocol::Status => None,
|
||||
Protocol::Goodbye => None,
|
||||
Protocol::BlocksByRange => Some(ResponseTermination::BlocksByRange),
|
||||
Protocol::BlocksByRoot => Some(ResponseTermination::BlocksByRoot),
|
||||
Protocol::BlobsByRange => Some(ResponseTermination::BlobsByRange),
|
||||
Protocol::BlobsByRoot => Some(ResponseTermination::BlobsByRoot),
|
||||
Protocol::Ping => None,
|
||||
Protocol::MetaData => None,
|
||||
Protocol::LightClientBootstrap => None,
|
||||
SupportedProtocol::StatusV1 => "1",
|
||||
SupportedProtocol::GoodbyeV1 => "1",
|
||||
SupportedProtocol::BlocksByRangeV1 => "1",
|
||||
SupportedProtocol::BlocksByRangeV2 => "2",
|
||||
SupportedProtocol::BlocksByRootV1 => "1",
|
||||
SupportedProtocol::BlocksByRootV2 => "2",
|
||||
SupportedProtocol::BlobsByRangeV1 => "1",
|
||||
SupportedProtocol::BlobsByRootV1 => "1",
|
||||
SupportedProtocol::PingV1 => "1",
|
||||
SupportedProtocol::MetaDataV1 => "1",
|
||||
SupportedProtocol::MetaDataV2 => "2",
|
||||
SupportedProtocol::LightClientBootstrapV1 => "1",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn protocol(&self) -> Protocol {
|
||||
match self {
|
||||
SupportedProtocol::StatusV1 => Protocol::Status,
|
||||
SupportedProtocol::GoodbyeV1 => Protocol::Goodbye,
|
||||
SupportedProtocol::BlocksByRangeV1 => Protocol::BlocksByRange,
|
||||
SupportedProtocol::BlocksByRangeV2 => Protocol::BlocksByRange,
|
||||
SupportedProtocol::BlocksByRootV1 => Protocol::BlocksByRoot,
|
||||
SupportedProtocol::BlocksByRootV2 => Protocol::BlocksByRoot,
|
||||
SupportedProtocol::BlobsByRangeV1 => Protocol::BlobsByRange,
|
||||
SupportedProtocol::BlobsByRootV1 => Protocol::BlobsByRoot,
|
||||
SupportedProtocol::PingV1 => Protocol::Ping,
|
||||
SupportedProtocol::MetaDataV1 => Protocol::MetaData,
|
||||
SupportedProtocol::MetaDataV2 => Protocol::MetaData,
|
||||
SupportedProtocol::LightClientBootstrapV1 => Protocol::LightClientBootstrap,
|
||||
}
|
||||
}
|
||||
|
||||
fn currently_supported() -> Vec<ProtocolId> {
|
||||
vec![
|
||||
ProtocolId::new(Self::StatusV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::GoodbyeV1, Encoding::SSZSnappy),
|
||||
// V2 variants have higher preference then V1
|
||||
ProtocolId::new(Self::BlocksByRangeV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::BlocksByRangeV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::BlocksByRootV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::BlocksByRootV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::BlobsByRangeV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::BlobsByRootV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::PingV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::MetaDataV2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Self::MetaDataV1, Encoding::SSZSnappy),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Encoding {
|
||||
@@ -245,16 +290,6 @@ impl std::fmt::Display for Encoding {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Version {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let repr = match self {
|
||||
Version::V1 => "1",
|
||||
Version::V2 => "2",
|
||||
};
|
||||
f.write_str(repr)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RPCProtocol<TSpec: EthSpec> {
|
||||
pub fork_context: Arc<ForkContext>,
|
||||
@@ -269,30 +304,17 @@ impl<TSpec: EthSpec> UpgradeInfo for RPCProtocol<TSpec> {
|
||||
|
||||
/// The list of supported RPC protocols for Lighthouse.
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
let mut supported_protocols = vec![
|
||||
ProtocolId::new(Protocol::Status, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::Goodbye, Version::V1, Encoding::SSZSnappy),
|
||||
// V2 variants have higher preference then V1
|
||||
ProtocolId::new(Protocol::BlocksByRange, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlocksByRange, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlocksByRoot, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlocksByRoot, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::Ping, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::MetaData, Version::V2, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::MetaData, Version::V1, Encoding::SSZSnappy),
|
||||
];
|
||||
let mut supported_protocols = SupportedProtocol::currently_supported();
|
||||
|
||||
if let ForkName::Deneb = self.fork_context.current_fork() {
|
||||
supported_protocols.extend_from_slice(&[
|
||||
ProtocolId::new(Protocol::BlobsByRoot, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(Protocol::BlobsByRange, Version::V1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::BlobsByRootV1, Encoding::SSZSnappy),
|
||||
ProtocolId::new(SupportedProtocol::BlobsByRangeV1, Encoding::SSZSnappy),
|
||||
]);
|
||||
}
|
||||
|
||||
if self.enable_light_client_server {
|
||||
supported_protocols.push(ProtocolId::new(
|
||||
Protocol::LightClientBootstrap,
|
||||
Version::V1,
|
||||
SupportedProtocol::LightClientBootstrapV1,
|
||||
Encoding::SSZSnappy,
|
||||
));
|
||||
}
|
||||
@@ -322,11 +344,8 @@ impl RpcLimits {
|
||||
/// Tracks the types in a protocol id.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProtocolId {
|
||||
/// The RPC message type/name.
|
||||
pub message_name: Protocol,
|
||||
|
||||
/// The version of the RPC.
|
||||
pub version: Version,
|
||||
/// The protocol name and version
|
||||
pub versioned_protocol: SupportedProtocol,
|
||||
|
||||
/// The encoding of the RPC.
|
||||
pub encoding: Encoding,
|
||||
@@ -338,7 +357,7 @@ pub struct ProtocolId {
|
||||
impl ProtocolId {
|
||||
/// Returns min and max size for messages of given protocol id requests.
|
||||
pub fn rpc_request_limits(&self) -> RpcLimits {
|
||||
match self.message_name {
|
||||
match self.versioned_protocol.protocol() {
|
||||
Protocol::Status => RpcLimits::new(
|
||||
<StatusMessage as Encode>::ssz_fixed_len(),
|
||||
<StatusMessage as Encode>::ssz_fixed_len(),
|
||||
@@ -347,9 +366,10 @@ impl ProtocolId {
|
||||
<GoodbyeReason as Encode>::ssz_fixed_len(),
|
||||
<GoodbyeReason as Encode>::ssz_fixed_len(),
|
||||
),
|
||||
// V1 and V2 requests are the same
|
||||
Protocol::BlocksByRange => RpcLimits::new(
|
||||
<OldBlocksByRangeRequest as Encode>::ssz_fixed_len(),
|
||||
<OldBlocksByRangeRequest as Encode>::ssz_fixed_len(),
|
||||
<OldBlocksByRangeRequestV2 as Encode>::ssz_fixed_len(),
|
||||
<OldBlocksByRangeRequestV2 as Encode>::ssz_fixed_len(),
|
||||
),
|
||||
Protocol::BlocksByRoot => {
|
||||
RpcLimits::new(*BLOCKS_BY_ROOT_REQUEST_MIN, *BLOCKS_BY_ROOT_REQUEST_MAX)
|
||||
@@ -376,7 +396,7 @@ impl ProtocolId {
|
||||
|
||||
/// Returns min and max size for messages of given protocol id responses.
|
||||
pub fn rpc_response_limits<T: EthSpec>(&self, fork_context: &ForkContext) -> RpcLimits {
|
||||
match self.message_name {
|
||||
match self.versioned_protocol.protocol() {
|
||||
Protocol::Status => RpcLimits::new(
|
||||
<StatusMessage as Encode>::ssz_fixed_len(),
|
||||
<StatusMessage as Encode>::ssz_fixed_len(),
|
||||
@@ -407,31 +427,36 @@ impl ProtocolId {
|
||||
/// Returns `true` if the given `ProtocolId` should expect `context_bytes` in the
|
||||
/// beginning of the stream, else returns `false`.
|
||||
pub fn has_context_bytes(&self) -> bool {
|
||||
match self.message_name {
|
||||
Protocol::BlocksByRange | Protocol::BlocksByRoot => match self.version {
|
||||
Version::V2 => true,
|
||||
Version::V1 => false,
|
||||
},
|
||||
Protocol::LightClientBootstrap => match self.version {
|
||||
Version::V2 | Version::V1 => true,
|
||||
},
|
||||
Protocol::BlobsByRoot | Protocol::BlobsByRange => true,
|
||||
Protocol::Goodbye | Protocol::Ping | Protocol::Status | Protocol::MetaData => false,
|
||||
match self.versioned_protocol {
|
||||
SupportedProtocol::BlocksByRangeV2
|
||||
| SupportedProtocol::BlocksByRootV2
|
||||
| SupportedProtocol::BlobsByRangeV1
|
||||
| SupportedProtocol::BlobsByRootV1
|
||||
| SupportedProtocol::LightClientBootstrapV1 => true,
|
||||
SupportedProtocol::StatusV1
|
||||
| SupportedProtocol::BlocksByRootV1
|
||||
| SupportedProtocol::BlocksByRangeV1
|
||||
| SupportedProtocol::PingV1
|
||||
| SupportedProtocol::MetaDataV1
|
||||
| SupportedProtocol::MetaDataV2
|
||||
| SupportedProtocol::GoodbyeV1 => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An RPC protocol ID.
|
||||
impl ProtocolId {
|
||||
pub fn new(message_name: Protocol, version: Version, encoding: Encoding) -> Self {
|
||||
pub fn new(versioned_protocol: SupportedProtocol, encoding: Encoding) -> Self {
|
||||
let protocol_id = format!(
|
||||
"{}/{}/{}/{}",
|
||||
PROTOCOL_PREFIX, message_name, version, encoding
|
||||
PROTOCOL_PREFIX,
|
||||
versioned_protocol.protocol(),
|
||||
versioned_protocol.version_string(),
|
||||
encoding
|
||||
);
|
||||
|
||||
ProtocolId {
|
||||
message_name,
|
||||
version,
|
||||
versioned_protocol,
|
||||
encoding,
|
||||
protocol_id,
|
||||
}
|
||||
@@ -464,7 +489,7 @@ where
|
||||
|
||||
fn upgrade_inbound(self, socket: TSocket, protocol: ProtocolId) -> Self::Future {
|
||||
async move {
|
||||
let protocol_name = protocol.message_name;
|
||||
let versioned_protocol = protocol.versioned_protocol;
|
||||
// convert the socket to tokio compatible socket
|
||||
let socket = socket.compat();
|
||||
let codec = match protocol.encoding {
|
||||
@@ -483,8 +508,13 @@ where
|
||||
let socket = Framed::new(Box::pin(timed_socket), codec);
|
||||
|
||||
// MetaData requests should be empty, return the stream
|
||||
match protocol_name {
|
||||
Protocol::MetaData => Ok((InboundRequest::MetaData(PhantomData), socket)),
|
||||
match versioned_protocol {
|
||||
SupportedProtocol::MetaDataV1 => {
|
||||
Ok((InboundRequest::MetaData(MetadataRequest::new_v1()), socket))
|
||||
}
|
||||
SupportedProtocol::MetaDataV2 => {
|
||||
Ok((InboundRequest::MetaData(MetadataRequest::new_v2()), socket))
|
||||
}
|
||||
_ => {
|
||||
match tokio::time::timeout(
|
||||
Duration::from_secs(REQUEST_TIMEOUT),
|
||||
@@ -514,7 +544,7 @@ pub enum InboundRequest<TSpec: EthSpec> {
|
||||
BlobsByRoot(BlobsByRootRequest),
|
||||
LightClientBootstrap(LightClientBootstrapRequest),
|
||||
Ping(Ping),
|
||||
MetaData(PhantomData<TSpec>),
|
||||
MetaData(MetadataRequest<TSpec>),
|
||||
}
|
||||
|
||||
/// Implements the encoding per supported protocol for `RPCRequest`.
|
||||
@@ -526,8 +556,8 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
|
||||
match self {
|
||||
InboundRequest::Status(_) => 1,
|
||||
InboundRequest::Goodbye(_) => 0,
|
||||
InboundRequest::BlocksByRange(req) => req.count,
|
||||
InboundRequest::BlocksByRoot(req) => req.block_roots.len() as u64,
|
||||
InboundRequest::BlocksByRange(req) => *req.count(),
|
||||
InboundRequest::BlocksByRoot(req) => req.block_roots().len() as u64,
|
||||
InboundRequest::BlobsByRange(req) => req.count * TSpec::max_blobs_per_block() as u64,
|
||||
InboundRequest::BlobsByRoot(req) => req.blob_ids.len() as u64,
|
||||
InboundRequest::Ping(_) => 1,
|
||||
@@ -536,18 +566,27 @@ impl<TSpec: EthSpec> InboundRequest<TSpec> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gives the corresponding `Protocol` to this request.
|
||||
pub fn protocol(&self) -> Protocol {
|
||||
/// Gives the corresponding `SupportedProtocol` to this request.
|
||||
pub fn versioned_protocol(&self) -> SupportedProtocol {
|
||||
match self {
|
||||
InboundRequest::Status(_) => Protocol::Status,
|
||||
InboundRequest::Goodbye(_) => Protocol::Goodbye,
|
||||
InboundRequest::BlocksByRange(_) => Protocol::BlocksByRange,
|
||||
InboundRequest::BlocksByRoot(_) => Protocol::BlocksByRoot,
|
||||
InboundRequest::BlobsByRange(_) => Protocol::BlobsByRange,
|
||||
InboundRequest::BlobsByRoot(_) => Protocol::BlobsByRoot,
|
||||
InboundRequest::Ping(_) => Protocol::Ping,
|
||||
InboundRequest::MetaData(_) => Protocol::MetaData,
|
||||
InboundRequest::LightClientBootstrap(_) => Protocol::LightClientBootstrap,
|
||||
InboundRequest::Status(_) => SupportedProtocol::StatusV1,
|
||||
InboundRequest::Goodbye(_) => SupportedProtocol::GoodbyeV1,
|
||||
InboundRequest::BlocksByRange(req) => match req {
|
||||
OldBlocksByRangeRequest::V1(_) => SupportedProtocol::BlocksByRangeV1,
|
||||
OldBlocksByRangeRequest::V2(_) => SupportedProtocol::BlocksByRangeV2,
|
||||
},
|
||||
InboundRequest::BlocksByRoot(req) => match req {
|
||||
BlocksByRootRequest::V1(_) => SupportedProtocol::BlocksByRootV1,
|
||||
BlocksByRootRequest::V2(_) => SupportedProtocol::BlocksByRootV2,
|
||||
},
|
||||
InboundRequest::BlobsByRange(_) => SupportedProtocol::BlobsByRangeV1,
|
||||
InboundRequest::BlobsByRoot(_) => SupportedProtocol::BlobsByRootV1,
|
||||
InboundRequest::Ping(_) => SupportedProtocol::PingV1,
|
||||
InboundRequest::MetaData(req) => match req {
|
||||
MetadataRequest::V1(_) => SupportedProtocol::MetaDataV1,
|
||||
MetadataRequest::V2(_) => SupportedProtocol::MetaDataV2,
|
||||
},
|
||||
InboundRequest::LightClientBootstrap(_) => SupportedProtocol::LightClientBootstrapV1,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ pub trait RateLimiterItem {
|
||||
|
||||
impl<T: EthSpec> RateLimiterItem for super::InboundRequest<T> {
|
||||
fn protocol(&self) -> Protocol {
|
||||
self.protocol()
|
||||
self.versioned_protocol().protocol()
|
||||
}
|
||||
|
||||
fn expected_responses(&self) -> u64 {
|
||||
@@ -224,7 +224,7 @@ impl<T: EthSpec> RateLimiterItem for super::InboundRequest<T> {
|
||||
|
||||
impl<T: EthSpec> RateLimiterItem for super::OutboundRequest<T> {
|
||||
fn protocol(&self) -> Protocol {
|
||||
self.protocol()
|
||||
self.versioned_protocol().protocol()
|
||||
}
|
||||
|
||||
fn expected_responses(&self) -> u64 {
|
||||
|
||||
@@ -72,7 +72,7 @@ impl<Id: ReqId, TSpec: EthSpec> SelfRateLimiter<Id, TSpec> {
|
||||
request_id: Id,
|
||||
req: OutboundRequest<TSpec>,
|
||||
) -> Result<BehaviourAction<Id, TSpec>, Error> {
|
||||
let protocol = req.protocol();
|
||||
let protocol = req.versioned_protocol().protocol();
|
||||
// First check that there are not already other requests waiting to be sent.
|
||||
if let Some(queued_requests) = self.delayed_requests.get_mut(&(peer_id, protocol)) {
|
||||
queued_requests.push_back(QueuedRequest { req, request_id });
|
||||
@@ -111,7 +111,7 @@ impl<Id: ReqId, TSpec: EthSpec> SelfRateLimiter<Id, TSpec> {
|
||||
event: RPCSend::Request(request_id, req),
|
||||
}),
|
||||
Err(e) => {
|
||||
let protocol = req.protocol();
|
||||
let protocol = req.versioned_protocol();
|
||||
match e {
|
||||
RateLimitedErr::TooLarge => {
|
||||
// this should never happen with default parameters. Let's just send the request.
|
||||
@@ -119,7 +119,7 @@ impl<Id: ReqId, TSpec: EthSpec> SelfRateLimiter<Id, TSpec> {
|
||||
crit!(
|
||||
log,
|
||||
"Self rate limiting error for a batch that will never fit. Sending request anyway. Check configuration parameters.";
|
||||
"protocol" => %req.protocol()
|
||||
"protocol" => %req.versioned_protocol().protocol()
|
||||
);
|
||||
Ok(BehaviourAction::NotifyHandler {
|
||||
peer_id,
|
||||
@@ -128,7 +128,7 @@ impl<Id: ReqId, TSpec: EthSpec> SelfRateLimiter<Id, TSpec> {
|
||||
})
|
||||
}
|
||||
RateLimitedErr::TooSoon(wait_time) => {
|
||||
debug!(log, "Self rate limiting"; "protocol" => %protocol, "wait_time_ms" => wait_time.as_millis(), "peer_id" => %peer_id);
|
||||
debug!(log, "Self rate limiting"; "protocol" => %protocol.protocol(), "wait_time_ms" => wait_time.as_millis(), "peer_id" => %peer_id);
|
||||
Err((QueuedRequest { req, request_id }, wait_time))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ use crate::rpc::methods::{BlobsByRangeRequest, BlobsByRootRequest};
|
||||
use crate::rpc::{
|
||||
methods::{
|
||||
BlocksByRangeRequest, BlocksByRootRequest, LightClientBootstrapRequest,
|
||||
OldBlocksByRangeRequest, RPCCodedResponse, RPCResponse, ResponseTermination, StatusMessage,
|
||||
OldBlocksByRangeRequest, OldBlocksByRangeRequestV1, OldBlocksByRangeRequestV2,
|
||||
RPCCodedResponse, RPCResponse, ResponseTermination, StatusMessage,
|
||||
},
|
||||
OutboundRequest, SubstreamId,
|
||||
};
|
||||
@@ -48,15 +49,26 @@ impl<TSpec: EthSpec> std::convert::From<Request> for OutboundRequest<TSpec> {
|
||||
fn from(req: Request) -> OutboundRequest<TSpec> {
|
||||
match req {
|
||||
Request::BlocksByRoot(r) => OutboundRequest::BlocksByRoot(r),
|
||||
Request::BlocksByRange(BlocksByRangeRequest { start_slot, count }) => {
|
||||
OutboundRequest::BlocksByRange(OldBlocksByRangeRequest {
|
||||
start_slot,
|
||||
count,
|
||||
step: 1,
|
||||
})
|
||||
Request::BlocksByRange(r) => match r {
|
||||
BlocksByRangeRequest::V1(req) => OutboundRequest::BlocksByRange(
|
||||
OldBlocksByRangeRequest::V1(OldBlocksByRangeRequestV1 {
|
||||
start_slot: req.start_slot,
|
||||
count: req.count,
|
||||
step: 1,
|
||||
}),
|
||||
),
|
||||
BlocksByRangeRequest::V2(req) => OutboundRequest::BlocksByRange(
|
||||
OldBlocksByRangeRequest::V2(OldBlocksByRangeRequestV2 {
|
||||
start_slot: req.start_slot,
|
||||
count: req.count,
|
||||
step: 1,
|
||||
}),
|
||||
),
|
||||
},
|
||||
Request::LightClientBootstrap(_) => {
|
||||
unreachable!("Lighthouse never makes an outbound light client request")
|
||||
}
|
||||
Request::BlobsByRange(r) => OutboundRequest::BlobsByRange(r),
|
||||
Request::LightClientBootstrap(b) => OutboundRequest::LightClientBootstrap(b),
|
||||
Request::BlobsByRoot(r) => OutboundRequest::BlobsByRoot(r),
|
||||
Request::Status(s) => OutboundRequest::Status(s),
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::peer_manager::{
|
||||
ConnectionDirection, PeerManager, PeerManagerEvent,
|
||||
};
|
||||
use crate::peer_manager::{MIN_OUTBOUND_ONLY_FACTOR, PEER_EXCESS_FACTOR, PRIORITY_PEER_EXCESS};
|
||||
use crate::rpc::methods::MetadataRequest;
|
||||
use crate::rpc::*;
|
||||
use crate::service::behaviour::BehaviourEvent;
|
||||
pub use crate::service::behaviour::Gossipsub;
|
||||
@@ -37,7 +38,6 @@ use slog::{crit, debug, info, o, trace, warn};
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
use std::{
|
||||
marker::PhantomData,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
@@ -949,16 +949,25 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
|
||||
/// Sends a METADATA request to a peer.
|
||||
fn send_meta_data_request(&mut self, peer_id: PeerId) {
|
||||
let event = OutboundRequest::MetaData(PhantomData);
|
||||
// We always prefer sending V2 requests
|
||||
let event = OutboundRequest::MetaData(MetadataRequest::new_v2());
|
||||
self.eth2_rpc_mut()
|
||||
.send_request(peer_id, RequestId::Internal, event);
|
||||
}
|
||||
|
||||
/// Sends a METADATA response to a peer.
|
||||
fn send_meta_data_response(&mut self, id: PeerRequestId, peer_id: PeerId) {
|
||||
let event = RPCCodedResponse::Success(RPCResponse::MetaData(
|
||||
self.network_globals.local_metadata.read().clone(),
|
||||
));
|
||||
fn send_meta_data_response(
|
||||
&mut self,
|
||||
req: MetadataRequest<TSpec>,
|
||||
id: PeerRequestId,
|
||||
peer_id: PeerId,
|
||||
) {
|
||||
let metadata = self.network_globals.local_metadata.read().clone();
|
||||
let metadata = match req {
|
||||
MetadataRequest::V1(_) => metadata.metadata_v1(),
|
||||
MetadataRequest::V2(_) => metadata,
|
||||
};
|
||||
let event = RPCCodedResponse::Success(RPCResponse::MetaData(metadata));
|
||||
self.eth2_rpc_mut().send_response(peer_id, id, event);
|
||||
}
|
||||
|
||||
@@ -1207,9 +1216,9 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
self.pong(peer_request_id, peer_id);
|
||||
None
|
||||
}
|
||||
InboundRequest::MetaData(_) => {
|
||||
InboundRequest::MetaData(req) => {
|
||||
// send the requested meta-data
|
||||
self.send_meta_data_response((handler_id, id), peer_id);
|
||||
self.send_meta_data_response(req, (handler_id, id), peer_id);
|
||||
None
|
||||
}
|
||||
InboundRequest::Goodbye(reason) => {
|
||||
@@ -1236,13 +1245,9 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
Some(event)
|
||||
}
|
||||
InboundRequest::BlocksByRange(req) => {
|
||||
let methods::OldBlocksByRangeRequest {
|
||||
start_slot,
|
||||
mut count,
|
||||
step,
|
||||
} = req;
|
||||
// Still disconnect the peer if the request is naughty.
|
||||
if step == 0 {
|
||||
let mut count = *req.count();
|
||||
if *req.step() == 0 {
|
||||
self.peer_manager_mut().handle_rpc_error(
|
||||
&peer_id,
|
||||
Protocol::BlocksByRange,
|
||||
@@ -1254,14 +1259,18 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
||||
return None;
|
||||
}
|
||||
// return just one block in case the step parameter is used. https://github.com/ethereum/consensus-specs/pull/2856
|
||||
if step > 1 {
|
||||
if *req.step() > 1 {
|
||||
count = 1;
|
||||
}
|
||||
let event = self.build_request(
|
||||
peer_request_id,
|
||||
peer_id,
|
||||
Request::BlocksByRange(BlocksByRangeRequest { start_slot, count }),
|
||||
);
|
||||
let request = match req {
|
||||
methods::OldBlocksByRangeRequest::V1(req) => Request::BlocksByRange(
|
||||
BlocksByRangeRequest::new_v1(req.start_slot, count),
|
||||
),
|
||||
methods::OldBlocksByRangeRequest::V2(req) => Request::BlocksByRange(
|
||||
BlocksByRangeRequest::new(req.start_slot, count),
|
||||
),
|
||||
};
|
||||
let event = self.build_request(peer_request_id, peer_id, request);
|
||||
Some(event)
|
||||
}
|
||||
InboundRequest::BlocksByRoot(req) => {
|
||||
|
||||
@@ -276,9 +276,11 @@ pub(crate) fn save_metadata_to_disk<E: EthSpec>(
|
||||
log: &slog::Logger,
|
||||
) {
|
||||
let _ = std::fs::create_dir_all(dir);
|
||||
match File::create(dir.join(METADATA_FILENAME))
|
||||
.and_then(|mut f| f.write_all(&metadata.as_ssz_bytes()))
|
||||
{
|
||||
let metadata_bytes = match metadata {
|
||||
MetaData::V1(md) => md.as_ssz_bytes(),
|
||||
MetaData::V2(md) => md.as_ssz_bytes(),
|
||||
};
|
||||
match File::create(dir.join(METADATA_FILENAME)).and_then(|mut f| f.write_all(&metadata_bytes)) {
|
||||
Ok(_) => {
|
||||
debug!(log, "Metadata written to disk");
|
||||
}
|
||||
|
||||
@@ -155,10 +155,7 @@ fn test_blocks_by_range_chunked_rpc() {
|
||||
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Merge).await;
|
||||
|
||||
// BlocksByRange Request
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest {
|
||||
start_slot: 0,
|
||||
count: messages_to_send,
|
||||
});
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send));
|
||||
|
||||
let spec = E::default_spec();
|
||||
|
||||
@@ -282,10 +279,7 @@ fn test_blocks_by_range_over_limit() {
|
||||
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Merge).await;
|
||||
|
||||
// BlocksByRange Request
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest {
|
||||
start_slot: 0,
|
||||
count: messages_to_send,
|
||||
});
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send));
|
||||
|
||||
// BlocksByRange Response
|
||||
let full_block = merge_block_large(&common::fork_context(ForkName::Merge));
|
||||
@@ -367,10 +361,7 @@ fn test_blocks_by_range_chunked_rpc_terminates_correctly() {
|
||||
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base).await;
|
||||
|
||||
// BlocksByRange Request
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest {
|
||||
start_slot: 0,
|
||||
count: messages_to_send,
|
||||
});
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, messages_to_send));
|
||||
|
||||
// BlocksByRange Response
|
||||
let spec = E::default_spec();
|
||||
@@ -490,10 +481,7 @@ fn test_blocks_by_range_single_empty_rpc() {
|
||||
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base).await;
|
||||
|
||||
// BlocksByRange Request
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest {
|
||||
start_slot: 0,
|
||||
count: 10,
|
||||
});
|
||||
let rpc_request = Request::BlocksByRange(BlocksByRangeRequest::new(0, 10));
|
||||
|
||||
// BlocksByRange Response
|
||||
let spec = E::default_spec();
|
||||
@@ -594,16 +582,15 @@ fn test_blocks_by_root_chunked_rpc() {
|
||||
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Merge).await;
|
||||
|
||||
// BlocksByRoot Request
|
||||
let rpc_request = Request::BlocksByRoot(BlocksByRootRequest {
|
||||
block_roots: VariableList::from(vec![
|
||||
let rpc_request =
|
||||
Request::BlocksByRoot(BlocksByRootRequest::new(VariableList::from(vec![
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
]),
|
||||
});
|
||||
])));
|
||||
|
||||
// BlocksByRoot Response
|
||||
let full_block = BeaconBlock::Base(BeaconBlockBase::<E>::full(&spec));
|
||||
@@ -722,8 +709,8 @@ fn test_blocks_by_root_chunked_rpc_terminates_correctly() {
|
||||
common::build_node_pair(Arc::downgrade(&rt), &log, ForkName::Base).await;
|
||||
|
||||
// BlocksByRoot Request
|
||||
let rpc_request = Request::BlocksByRoot(BlocksByRootRequest {
|
||||
block_roots: VariableList::from(vec![
|
||||
let rpc_request =
|
||||
Request::BlocksByRoot(BlocksByRootRequest::new(VariableList::from(vec![
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
@@ -734,8 +721,7 @@ fn test_blocks_by_root_chunked_rpc_terminates_correctly() {
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
Hash256::from_low_u64_be(0),
|
||||
]),
|
||||
});
|
||||
])));
|
||||
|
||||
// BlocksByRoot Response
|
||||
let full_block = BeaconBlock::Base(BeaconBlockBase::<E>::full(&spec));
|
||||
|
||||
@@ -9,8 +9,8 @@ use beacon_chain::{
|
||||
observed_operations::ObservationOutcome,
|
||||
sync_committee_verification::{self, Error as SyncCommitteeError},
|
||||
validator_monitor::get_block_delay_ms,
|
||||
AvailabilityProcessingStatus, BeaconChainError, BeaconChainTypes, BlockError, CountUnrealized,
|
||||
ForkChoiceError, GossipVerifiedBlock, NotifyExecutionLayer,
|
||||
AvailabilityProcessingStatus, BeaconChainError, BeaconChainTypes, BlockError, ForkChoiceError,
|
||||
GossipVerifiedBlock, NotifyExecutionLayer,
|
||||
};
|
||||
use lighthouse_network::{Client, MessageAcceptance, MessageId, PeerAction, PeerId, ReportSource};
|
||||
use operation_pool::ReceivedPreCapella;
|
||||
@@ -756,11 +756,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
let blob_root = verified_blob.block_root();
|
||||
let blob_slot = verified_blob.slot();
|
||||
let blob_clone = verified_blob.clone().to_blob();
|
||||
match self
|
||||
.chain
|
||||
.process_blob(verified_blob, CountUnrealized::True)
|
||||
.await
|
||||
{
|
||||
match self.chain.process_blob(verified_blob).await {
|
||||
Ok(AvailabilityProcessingStatus::Imported(_hash)) => {
|
||||
//TODO(sean) add metrics and logging
|
||||
self.chain.recompute_head_at_current_slot().await;
|
||||
@@ -978,7 +974,6 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
| Err(e @ BlockError::NonLinearParentRoots)
|
||||
| Err(e @ BlockError::BlockIsNotLaterThanParent { .. })
|
||||
| Err(e @ BlockError::InvalidSignature)
|
||||
| Err(e @ BlockError::TooManySkippedSlots { .. })
|
||||
| Err(e @ BlockError::WeakSubjectivityConflict)
|
||||
| Err(e @ BlockError::InconsistentFork(_))
|
||||
| Err(e @ BlockError::ExecutionPayloadError(_))
|
||||
@@ -1103,12 +1098,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
|
||||
let result = self
|
||||
.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
verified_block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_block(block_root, verified_block, NotifyExecutionLayer::Yes)
|
||||
.await;
|
||||
|
||||
match &result {
|
||||
|
||||
@@ -139,10 +139,10 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
request_id: PeerRequestId,
|
||||
request: BlocksByRootRequest,
|
||||
) {
|
||||
let requested_blocks = request.block_roots.len();
|
||||
let requested_blocks = request.block_roots().len();
|
||||
let mut block_stream = match self
|
||||
.chain
|
||||
.get_blocks_checking_early_attester_cache(request.block_roots.into(), &executor)
|
||||
.get_blocks_checking_early_attester_cache(request.block_roots().to_vec(), &executor)
|
||||
{
|
||||
Ok(block_stream) => block_stream,
|
||||
Err(e) => return error!(self.log, "Error getting block stream"; "error" => ?e),
|
||||
@@ -375,27 +375,22 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
send_on_drop: SendOnDrop,
|
||||
peer_id: PeerId,
|
||||
request_id: PeerRequestId,
|
||||
req: BlocksByRangeRequest,
|
||||
mut req: BlocksByRangeRequest,
|
||||
) {
|
||||
debug!(self.log, "Received BlocksByRange Request";
|
||||
"peer_id" => %peer_id,
|
||||
"count" => req.count,
|
||||
"start_slot" => req.start_slot,
|
||||
"count" => req.count(),
|
||||
"start_slot" => req.start_slot(),
|
||||
);
|
||||
|
||||
// Should not send more than max request blocks
|
||||
if req.count > MAX_REQUEST_BLOCKS {
|
||||
return self.send_error_response(
|
||||
peer_id,
|
||||
RPCResponseErrorCode::InvalidRequest,
|
||||
"Request exceeded `MAX_REQUEST_BLOBS_SIDECARS`".into(),
|
||||
request_id,
|
||||
);
|
||||
if *req.count() > MAX_REQUEST_BLOCKS {
|
||||
*req.count_mut() = MAX_REQUEST_BLOCKS;
|
||||
}
|
||||
|
||||
let forwards_block_root_iter = match self
|
||||
.chain
|
||||
.forwards_iter_block_roots(Slot::from(req.start_slot))
|
||||
.forwards_iter_block_roots(Slot::from(*req.start_slot()))
|
||||
{
|
||||
Ok(iter) => iter,
|
||||
Err(BeaconChainError::HistoricalBlockError(
|
||||
@@ -432,7 +427,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
|
||||
// Pick out the required blocks, ignoring skip-slots.
|
||||
let mut last_block_root = req
|
||||
.start_slot
|
||||
.start_slot()
|
||||
.checked_sub(1)
|
||||
.map(|prev_slot| {
|
||||
self.chain
|
||||
@@ -443,18 +438,20 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
.flatten()
|
||||
.flatten();
|
||||
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>>>()
|
||||
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 {
|
||||
@@ -487,8 +484,8 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
Ok(Some(block)) => {
|
||||
// Due to skip slots, blocks could be out of the range, we ensure they
|
||||
// are in the range before sending
|
||||
if block.slot() >= req.start_slot
|
||||
&& block.slot() < req.start_slot + req.count
|
||||
if block.slot() >= *req.start_slot()
|
||||
&& block.slot() < req.start_slot() + req.count()
|
||||
{
|
||||
blocks_sent += 1;
|
||||
self.send_network_message(NetworkMessage::SendResponse {
|
||||
@@ -572,15 +569,15 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
.slot()
|
||||
.unwrap_or_else(|_| self.chain.slot_clock.genesis_slot());
|
||||
|
||||
if blocks_sent < (req.count as usize) {
|
||||
if blocks_sent < (*req.count() as usize) {
|
||||
debug!(
|
||||
self.log,
|
||||
"BlocksByRange outgoing response processed";
|
||||
"peer" => %peer_id,
|
||||
"msg" => "Failed to return all requested blocks",
|
||||
"start_slot" => req.start_slot,
|
||||
"start_slot" => req.start_slot(),
|
||||
"current_slot" => current_slot,
|
||||
"requested" => req.count,
|
||||
"requested" => req.count(),
|
||||
"returned" => blocks_sent
|
||||
);
|
||||
} else {
|
||||
@@ -588,9 +585,9 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
self.log,
|
||||
"BlocksByRange outgoing response processed";
|
||||
"peer" => %peer_id,
|
||||
"start_slot" => req.start_slot,
|
||||
"start_slot" => req.start_slot(),
|
||||
"current_slot" => current_slot,
|
||||
"requested" => req.count,
|
||||
"requested" => req.count(),
|
||||
"returned" => blocks_sent
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ use crate::sync::{BatchProcessResult, ChainId};
|
||||
use beacon_chain::blob_verification::BlockWrapper;
|
||||
use beacon_chain::blob_verification::{AsBlock, MaybeAvailableBlock};
|
||||
use beacon_chain::data_availability_checker::AvailabilityCheckError;
|
||||
use beacon_chain::AvailabilityProcessingStatus;
|
||||
use beacon_chain::{
|
||||
observed_block_producers::Error as ObserveError, validator_monitor::get_block_delay_ms,
|
||||
BeaconChainError, BeaconChainTypes, BlockError, ChainSegmentResult, HistoricalBlockError,
|
||||
NotifyExecutionLayer,
|
||||
};
|
||||
use beacon_chain::{AvailabilityProcessingStatus, CountUnrealized};
|
||||
use lighthouse_network::PeerAction;
|
||||
use slog::{debug, error, info, warn};
|
||||
use slot_clock::SlotClock;
|
||||
@@ -28,7 +28,7 @@ use types::{Epoch, Hash256};
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum ChainSegmentProcessId {
|
||||
/// Processing Id of a range syncing batch.
|
||||
RangeBatchId(ChainId, Epoch, CountUnrealized),
|
||||
RangeBatchId(ChainId, Epoch),
|
||||
/// Processing ID for a backfill syncing batch.
|
||||
BackSyncBatchId(Epoch),
|
||||
/// Processing Id of the parent lookup of a block.
|
||||
@@ -171,12 +171,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
|
||||
let result = self
|
||||
.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
block,
|
||||
CountUnrealized::True,
|
||||
NotifyExecutionLayer::Yes,
|
||||
)
|
||||
.process_block(block_root, block, NotifyExecutionLayer::Yes)
|
||||
.await;
|
||||
|
||||
metrics::inc_counter(&metrics::BEACON_PROCESSOR_RPC_BLOCK_IMPORTED_TOTAL);
|
||||
@@ -233,15 +228,11 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
|
||||
let result = self
|
||||
.chain
|
||||
.check_availability_and_maybe_import(
|
||||
slot,
|
||||
|chain| {
|
||||
chain
|
||||
.data_availability_checker
|
||||
.put_rpc_blobs(block_root, blobs)
|
||||
},
|
||||
CountUnrealized::True,
|
||||
)
|
||||
.check_availability_and_maybe_import(slot, |chain| {
|
||||
chain
|
||||
.data_availability_checker
|
||||
.put_rpc_blobs(block_root, blobs)
|
||||
})
|
||||
.await;
|
||||
|
||||
// Sync handles these results
|
||||
@@ -262,17 +253,13 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
) {
|
||||
let result = match sync_type {
|
||||
// this a request from the range sync
|
||||
ChainSegmentProcessId::RangeBatchId(chain_id, epoch, count_unrealized) => {
|
||||
ChainSegmentProcessId::RangeBatchId(chain_id, epoch) => {
|
||||
let start_slot = downloaded_blocks.first().map(|b| b.slot().as_u64());
|
||||
let end_slot = downloaded_blocks.last().map(|b| b.slot().as_u64());
|
||||
let sent_blocks = downloaded_blocks.len();
|
||||
|
||||
match self
|
||||
.process_blocks(
|
||||
downloaded_blocks.iter(),
|
||||
count_unrealized,
|
||||
notify_execution_layer,
|
||||
)
|
||||
.process_blocks(downloaded_blocks.iter(), notify_execution_layer)
|
||||
.await
|
||||
{
|
||||
(_, Ok(_)) => {
|
||||
@@ -357,11 +344,7 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
// parent blocks are ordered from highest slot to lowest, so we need to process in
|
||||
// reverse
|
||||
match self
|
||||
.process_blocks(
|
||||
downloaded_blocks.iter().rev(),
|
||||
CountUnrealized::True,
|
||||
notify_execution_layer,
|
||||
)
|
||||
.process_blocks(downloaded_blocks.iter().rev(), notify_execution_layer)
|
||||
.await
|
||||
{
|
||||
(imported_blocks, Err(e)) => {
|
||||
@@ -391,13 +374,12 @@ impl<T: BeaconChainTypes> Worker<T> {
|
||||
async fn process_blocks<'a>(
|
||||
&self,
|
||||
downloaded_blocks: impl Iterator<Item = &'a BlockWrapper<T::EthSpec>>,
|
||||
count_unrealized: CountUnrealized,
|
||||
notify_execution_layer: NotifyExecutionLayer,
|
||||
) -> (usize, Result<(), ChainSegmentFailed>) {
|
||||
let blocks: Vec<_> = downloaded_blocks.cloned().collect();
|
||||
match self
|
||||
.chain
|
||||
.process_chain_segment(blocks, count_unrealized, notify_execution_layer)
|
||||
.process_chain_segment(blocks, notify_execution_layer)
|
||||
.await
|
||||
{
|
||||
ChainSegmentResult::Successful { imported_blocks } => {
|
||||
|
||||
@@ -491,9 +491,9 @@ impl<const MAX_ATTEMPTS: u8, T: BeaconChainTypes> SingleBlockLookup<MAX_ATTEMPTS
|
||||
self.block_request_state.state.state,
|
||||
State::AwaitingDownload
|
||||
));
|
||||
let request = BlocksByRootRequest {
|
||||
block_roots: VariableList::from(vec![self.block_request_state.requested_block_root]),
|
||||
};
|
||||
let request = BlocksByRootRequest::new(VariableList::from(vec![
|
||||
self.block_request_state.requested_block_root,
|
||||
]));
|
||||
let response_type = ResponseType::Block;
|
||||
if self.too_many_attempts(response_type) {
|
||||
Err(LookupRequestError::TooManyAttempts {
|
||||
|
||||
@@ -707,7 +707,7 @@ impl<T: BeaconChainTypes> SyncManager<T> {
|
||||
.parent_block_processed(chain_hash, result, response_type, &mut self.network),
|
||||
},
|
||||
SyncMessage::BatchProcessed { sync_type, result } => match sync_type {
|
||||
ChainSegmentProcessId::RangeBatchId(chain_id, epoch, _) => {
|
||||
ChainSegmentProcessId::RangeBatchId(chain_id, epoch) => {
|
||||
self.range_sync.handle_block_process_result(
|
||||
&mut self.network,
|
||||
chain_id,
|
||||
|
||||
@@ -162,7 +162,7 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
self.log,
|
||||
"Sending BlocksByRange request";
|
||||
"method" => "BlocksByRange",
|
||||
"count" => request.count,
|
||||
"count" => request.count(),
|
||||
"peer" => %peer_id,
|
||||
);
|
||||
let request = Request::BlocksByRange(request);
|
||||
@@ -181,7 +181,7 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
self.log,
|
||||
"Sending BlocksByRange and BlobsByRange requests";
|
||||
"method" => "Mixed by range request",
|
||||
"count" => request.count,
|
||||
"count" => request.count(),
|
||||
"peer" => %peer_id,
|
||||
);
|
||||
|
||||
@@ -191,8 +191,8 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
|
||||
// Create the blob request based on the blob request.
|
||||
let blobs_request = Request::BlobsByRange(BlobsByRangeRequest {
|
||||
start_slot: request.start_slot,
|
||||
count: request.count,
|
||||
start_slot: *request.start_slot(),
|
||||
count: *request.count(),
|
||||
});
|
||||
let blocks_request = Request::BlocksByRange(request);
|
||||
|
||||
@@ -235,7 +235,7 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
self.log,
|
||||
"Sending backfill BlocksByRange request";
|
||||
"method" => "BlocksByRange",
|
||||
"count" => request.count,
|
||||
"count" => request.count(),
|
||||
"peer" => %peer_id,
|
||||
);
|
||||
let request = Request::BlocksByRange(request);
|
||||
@@ -254,7 +254,7 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
self.log,
|
||||
"Sending backfill BlocksByRange and BlobsByRange requests";
|
||||
"method" => "Mixed by range request",
|
||||
"count" => request.count,
|
||||
"count" => request.count(),
|
||||
"peer" => %peer_id,
|
||||
);
|
||||
|
||||
@@ -264,8 +264,8 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
|
||||
// Create the blob request based on the blob request.
|
||||
let blobs_request = Request::BlobsByRange(BlobsByRangeRequest {
|
||||
start_slot: request.start_slot,
|
||||
count: request.count,
|
||||
start_slot: *request.start_slot(),
|
||||
count: *request.count(),
|
||||
});
|
||||
let blocks_request = Request::BlocksByRange(request);
|
||||
|
||||
@@ -422,7 +422,7 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
self.log,
|
||||
"Sending BlocksByRoot Request";
|
||||
"method" => "BlocksByRoot",
|
||||
"count" => request.block_roots.len(),
|
||||
"count" => request.block_roots().len(),
|
||||
"peer" => %peer_id
|
||||
);
|
||||
|
||||
@@ -472,7 +472,7 @@ impl<T: BeaconChainTypes> SyncNetworkContext<T> {
|
||||
self.log,
|
||||
"Sending parent BlocksByRoot Request";
|
||||
"method" => "BlocksByRoot",
|
||||
"count" => request.block_roots.len(),
|
||||
"count" => request.block_roots().len(),
|
||||
"peer" => %peer_id
|
||||
);
|
||||
|
||||
|
||||
@@ -220,10 +220,10 @@ impl<T: EthSpec, B: BatchConfig> BatchInfo<T, B> {
|
||||
/// Returns a BlocksByRange request associated with the batch.
|
||||
pub fn to_blocks_by_range_request(&self) -> (BlocksByRangeRequest, ByRangeRequestType) {
|
||||
(
|
||||
BlocksByRangeRequest {
|
||||
start_slot: self.start_slot.into(),
|
||||
count: self.end_slot.sub(self.start_slot).into(),
|
||||
},
|
||||
BlocksByRangeRequest::new(
|
||||
self.start_slot.into(),
|
||||
self.end_slot.sub(self.start_slot).into(),
|
||||
),
|
||||
self.batch_type,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::sync::{
|
||||
manager::Id, network_context::SyncNetworkContext, BatchOperationOutcome, BatchProcessResult,
|
||||
};
|
||||
use beacon_chain::blob_verification::BlockWrapper;
|
||||
use beacon_chain::{BeaconChainTypes, CountUnrealized};
|
||||
use beacon_chain::BeaconChainTypes;
|
||||
use fnv::FnvHashMap;
|
||||
use lighthouse_network::{PeerAction, PeerId};
|
||||
use rand::seq::SliceRandom;
|
||||
@@ -101,8 +101,6 @@ pub struct SyncingChain<T: BeaconChainTypes> {
|
||||
/// Batches validated by this chain.
|
||||
validated_batches: u64,
|
||||
|
||||
is_finalized_segment: bool,
|
||||
|
||||
/// The chain's log.
|
||||
log: slog::Logger,
|
||||
}
|
||||
@@ -128,7 +126,6 @@ impl<T: BeaconChainTypes> SyncingChain<T> {
|
||||
target_head_slot: Slot,
|
||||
target_head_root: Hash256,
|
||||
peer_id: PeerId,
|
||||
is_finalized_segment: bool,
|
||||
log: &slog::Logger,
|
||||
) -> Self {
|
||||
let mut peers = FnvHashMap::default();
|
||||
@@ -136,16 +133,10 @@ impl<T: BeaconChainTypes> SyncingChain<T> {
|
||||
|
||||
let id = SyncingChain::<T>::id(&target_head_root, &target_head_slot);
|
||||
|
||||
let target_slot = if is_finalized_segment {
|
||||
target_head_slot + (2 * T::EthSpec::slots_per_epoch()) + 1
|
||||
} else {
|
||||
target_head_slot
|
||||
};
|
||||
|
||||
SyncingChain {
|
||||
id,
|
||||
start_epoch,
|
||||
target_head_slot: target_slot,
|
||||
target_head_slot,
|
||||
target_head_root,
|
||||
batches: BTreeMap::new(),
|
||||
peers,
|
||||
@@ -156,7 +147,6 @@ impl<T: BeaconChainTypes> SyncingChain<T> {
|
||||
state: ChainSyncingState::Stopped,
|
||||
current_processing_batch: None,
|
||||
validated_batches: 0,
|
||||
is_finalized_segment,
|
||||
log: log.new(o!("chain" => id)),
|
||||
}
|
||||
}
|
||||
@@ -324,12 +314,7 @@ impl<T: BeaconChainTypes> SyncingChain<T> {
|
||||
// for removing chains and checking completion is in the callback.
|
||||
|
||||
let blocks = batch.start_processing()?;
|
||||
let count_unrealized = if self.is_finalized_segment {
|
||||
CountUnrealized::False
|
||||
} else {
|
||||
CountUnrealized::True
|
||||
};
|
||||
let process_id = ChainSegmentProcessId::RangeBatchId(self.id, batch_id, count_unrealized);
|
||||
let process_id = ChainSegmentProcessId::RangeBatchId(self.id, batch_id);
|
||||
self.current_processing_batch = Some(batch_id);
|
||||
|
||||
let work_event = BeaconWorkEvent::chain_segment(process_id, blocks);
|
||||
|
||||
@@ -465,10 +465,10 @@ impl<T: BeaconChainTypes, C: BlockStorage> ChainCollection<T, C> {
|
||||
network: &mut SyncNetworkContext<T>,
|
||||
) {
|
||||
let id = SyncingChain::<T>::id(&target_head_root, &target_head_slot);
|
||||
let (collection, is_finalized) = if let RangeSyncType::Finalized = sync_type {
|
||||
(&mut self.finalized_chains, true)
|
||||
let collection = if let RangeSyncType::Finalized = sync_type {
|
||||
&mut self.finalized_chains
|
||||
} else {
|
||||
(&mut self.head_chains, false)
|
||||
&mut self.head_chains
|
||||
};
|
||||
match collection.entry(id) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
@@ -493,7 +493,6 @@ impl<T: BeaconChainTypes, C: BlockStorage> ChainCollection<T, C> {
|
||||
target_head_slot,
|
||||
target_head_root,
|
||||
peer,
|
||||
is_finalized,
|
||||
&self.log,
|
||||
);
|
||||
debug_assert_eq!(new_chain.get_id(), id);
|
||||
|
||||
@@ -123,7 +123,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
.value_name("PORT")
|
||||
.help("The UDP port that discovery will listen on over IpV6 if listening over \
|
||||
both Ipv4 and IpV6. Defaults to `port6`")
|
||||
.hidden(true) // TODO: implement dual stack via two sockets in discv5.
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
@@ -205,7 +204,6 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
discovery. Set this only if you are sure other nodes can connect to your \
|
||||
local node on this address. This will update the `ip4` or `ip6` ENR fields \
|
||||
accordingly. To update both, set this flag twice with the different values.")
|
||||
.requires("enr-udp-port")
|
||||
.multiple(true)
|
||||
.max_values(2)
|
||||
.takes_value(true),
|
||||
@@ -729,7 +727,7 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
Arg::with_name("max-skip-slots")
|
||||
.long("max-skip-slots")
|
||||
.help(
|
||||
"Refuse to skip more than this many slots when processing a block or attestation. \
|
||||
"Refuse to skip more than this many slots when processing an attestation. \
|
||||
This prevents nodes on minority forks from wasting our time and disk space, \
|
||||
but could also cause unnecessary consensus failures, so is disabled by default."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user