mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-29 18:53:32 +00:00
Merge branch 'unstable' into deneb-free-blobs
# Conflicts: # .github/workflows/docker.yml # .github/workflows/local-testnet.yml # .github/workflows/test-suite.yml # Cargo.lock # Cargo.toml # beacon_node/beacon_chain/src/beacon_chain.rs # beacon_node/beacon_chain/src/builder.rs # beacon_node/beacon_chain/src/test_utils.rs # beacon_node/execution_layer/src/engine_api/json_structures.rs # beacon_node/network/src/beacon_processor/mod.rs # beacon_node/network/src/beacon_processor/worker/gossip_methods.rs # beacon_node/network/src/sync/backfill_sync/mod.rs # beacon_node/store/src/config.rs # beacon_node/store/src/hot_cold_store.rs # common/eth2_network_config/Cargo.toml # consensus/ssz/src/decode/impls.rs # consensus/ssz_derive/src/lib.rs # consensus/ssz_derive/tests/tests.rs # consensus/ssz_types/src/serde_utils/mod.rs # consensus/tree_hash/src/impls.rs # consensus/tree_hash/src/lib.rs # consensus/types/Cargo.toml # consensus/types/src/beacon_state.rs # consensus/types/src/chain_spec.rs # consensus/types/src/eth_spec.rs # consensus/types/src/fork_name.rs # lcli/Cargo.toml # lcli/src/main.rs # lcli/src/new_testnet.rs # scripts/local_testnet/el_bootnode.sh # scripts/local_testnet/genesis.json # scripts/local_testnet/geth.sh # scripts/local_testnet/setup.sh # scripts/local_testnet/start_local_testnet.sh # scripts/local_testnet/vars.env # scripts/tests/doppelganger_protection.sh # scripts/tests/genesis.json # scripts/tests/vars.env # testing/ef_tests/Cargo.toml # validator_client/src/block_service.rs
This commit is contained in:
@@ -12,6 +12,8 @@ use eth2::types::{BlockContents, SignedBlockContents};
|
||||
use eth2::BeaconNodeHttpClient;
|
||||
use slog::{crit, debug, error, info, trace, warn, Logger};
|
||||
use slot_clock::SlotClock;
|
||||
use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -48,6 +50,7 @@ pub struct BlockServiceBuilder<T, E: EthSpec> {
|
||||
validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
||||
slot_clock: Option<Arc<T>>,
|
||||
beacon_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||
proposer_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||
context: Option<RuntimeContext<E>>,
|
||||
graffiti: Option<Graffiti>,
|
||||
graffiti_file: Option<GraffitiFile>,
|
||||
@@ -60,6 +63,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
validator_store: None,
|
||||
slot_clock: None,
|
||||
beacon_nodes: None,
|
||||
proposer_nodes: None,
|
||||
context: None,
|
||||
graffiti: None,
|
||||
graffiti_file: None,
|
||||
@@ -82,6 +86,11 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn proposer_nodes(mut self, proposer_nodes: Arc<BeaconNodeFallback<T, E>>) -> Self {
|
||||
self.proposer_nodes = Some(proposer_nodes);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn runtime_context(mut self, context: RuntimeContext<E>) -> Self {
|
||||
self.context = Some(context);
|
||||
self
|
||||
@@ -117,6 +126,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
context: self
|
||||
.context
|
||||
.ok_or("Cannot build BlockService without runtime_context")?,
|
||||
proposer_nodes: self.proposer_nodes,
|
||||
graffiti: self.graffiti,
|
||||
graffiti_file: self.graffiti_file,
|
||||
block_delay: self.block_delay,
|
||||
@@ -125,11 +135,81 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockServiceBuilder<T, E> {
|
||||
}
|
||||
}
|
||||
|
||||
// Combines a set of non-block-proposing `beacon_nodes` and only-block-proposing
|
||||
// `proposer_nodes`.
|
||||
pub struct ProposerFallback<T, E: EthSpec> {
|
||||
beacon_nodes: Arc<BeaconNodeFallback<T, E>>,
|
||||
proposer_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||
}
|
||||
|
||||
impl<T: SlotClock, E: EthSpec> ProposerFallback<T, E> {
|
||||
// Try `func` on `self.proposer_nodes` first. If that doesn't work, try `self.beacon_nodes`.
|
||||
pub async fn first_success_try_proposers_first<'a, F, O, Err, R>(
|
||||
&'a self,
|
||||
require_synced: RequireSynced,
|
||||
offline_on_failure: OfflineOnFailure,
|
||||
func: F,
|
||||
) -> Result<O, Errors<Err>>
|
||||
where
|
||||
F: Fn(&'a BeaconNodeHttpClient) -> R + Clone,
|
||||
R: Future<Output = Result<O, Err>>,
|
||||
Err: Debug,
|
||||
{
|
||||
// If there are proposer nodes, try calling `func` on them and return early if they are successful.
|
||||
if let Some(proposer_nodes) = &self.proposer_nodes {
|
||||
if let Ok(result) = proposer_nodes
|
||||
.first_success(require_synced, offline_on_failure, func.clone())
|
||||
.await
|
||||
{
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
// If the proposer nodes failed, try on the non-proposer nodes.
|
||||
self.beacon_nodes
|
||||
.first_success(require_synced, offline_on_failure, func)
|
||||
.await
|
||||
}
|
||||
|
||||
// Try `func` on `self.beacon_nodes` first. If that doesn't work, try `self.proposer_nodes`.
|
||||
pub async fn first_success_try_proposers_last<'a, F, O, Err, R>(
|
||||
&'a self,
|
||||
require_synced: RequireSynced,
|
||||
offline_on_failure: OfflineOnFailure,
|
||||
func: F,
|
||||
) -> Result<O, Errors<Err>>
|
||||
where
|
||||
F: Fn(&'a BeaconNodeHttpClient) -> R + Clone,
|
||||
R: Future<Output = Result<O, Err>>,
|
||||
Err: Debug,
|
||||
{
|
||||
// Try running `func` on the non-proposer beacon nodes.
|
||||
let beacon_nodes_result = self
|
||||
.beacon_nodes
|
||||
.first_success(require_synced, offline_on_failure, func.clone())
|
||||
.await;
|
||||
|
||||
match (beacon_nodes_result, &self.proposer_nodes) {
|
||||
// The non-proposer node call succeed, return the result.
|
||||
(Ok(success), _) => Ok(success),
|
||||
// The non-proposer node call failed, but we don't have any proposer nodes. Return an error.
|
||||
(Err(e), None) => Err(e),
|
||||
// The non-proposer node call failed, try the same call on the proposer nodes.
|
||||
(Err(_), Some(proposer_nodes)) => {
|
||||
proposer_nodes
|
||||
.first_success(require_synced, offline_on_failure, func)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper to minimise `Arc` usage.
|
||||
pub struct Inner<T, E: EthSpec> {
|
||||
validator_store: Arc<ValidatorStore<T, E>>,
|
||||
slot_clock: Arc<T>,
|
||||
beacon_nodes: Arc<BeaconNodeFallback<T, E>>,
|
||||
proposer_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||
context: RuntimeContext<E>,
|
||||
graffiti: Option<Graffiti>,
|
||||
graffiti_file: Option<GraffitiFile>,
|
||||
@@ -337,16 +417,23 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
||||
let self_ref = &self;
|
||||
let proposer_index = self.validator_store.validator_index(&validator_pubkey);
|
||||
let validator_pubkey_ref = &validator_pubkey;
|
||||
let proposer_fallback = ProposerFallback {
|
||||
beacon_nodes: self.beacon_nodes.clone(),
|
||||
proposer_nodes: self.proposer_nodes.clone(),
|
||||
};
|
||||
|
||||
info!(
|
||||
log,
|
||||
"Requesting unsigned block";
|
||||
"slot" => slot.as_u64(),
|
||||
);
|
||||
|
||||
// Request block from first responsive beacon node.
|
||||
let block_contents = self
|
||||
.beacon_nodes
|
||||
.first_success(
|
||||
//
|
||||
// Try the proposer nodes last, since it's likely that they don't have a
|
||||
// great view of attestations on the network.
|
||||
let block_contents = proposer_fallback
|
||||
.first_success_try_proposers_last(
|
||||
RequireSynced::No,
|
||||
OfflineOnFailure::Yes,
|
||||
move |beacon_node| {
|
||||
@@ -397,8 +484,12 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
||||
let signed_block_contents = SignedBlockContents::from((signed_block, maybe_signed_blobs));
|
||||
|
||||
// Publish block with first available beacon node.
|
||||
self.beacon_nodes
|
||||
.first_success(
|
||||
//
|
||||
// Try the proposer nodes first, since we've likely gone to efforts to
|
||||
// protect them from DoS attacks and they're most likely to successfully
|
||||
// publish a block.
|
||||
proposer_fallback
|
||||
.first_success_try_proposers_first(
|
||||
RequireSynced::No,
|
||||
OfflineOnFailure::Yes,
|
||||
|beacon_node| async {
|
||||
|
||||
Reference in New Issue
Block a user