mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 20:57:10 +00:00
Merge branch 'unstable' into vc-fallback
This commit is contained in:
@@ -49,7 +49,6 @@ libsecp256k1 = { workspace = true }
|
||||
ring = { workspace = true }
|
||||
rand = { workspace = true, features = ["small_rng"] }
|
||||
lighthouse_metrics = { workspace = true }
|
||||
lazy_static = { workspace = true }
|
||||
monitoring_api = { workspace = true }
|
||||
sensitive_url = { workspace = true }
|
||||
task_executor = { workspace = true }
|
||||
|
||||
@@ -22,7 +22,6 @@ filesystem = { workspace = true }
|
||||
arbitrary = { workspace = true, features = ["derive"] }
|
||||
|
||||
[dev-dependencies]
|
||||
lazy_static = { workspace = true }
|
||||
rayon = { workspace = true }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use lazy_static::lazy_static;
|
||||
use slashing_protection::interchange_test::MultiTestCase;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref TEST_ROOT_DIR: PathBuf = test_root_dir();
|
||||
}
|
||||
pub static TEST_ROOT_DIR: LazyLock<PathBuf> = LazyLock::new(test_root_dir);
|
||||
|
||||
fn download_tests() {
|
||||
let make_output = std::process::Command::new("make")
|
||||
|
||||
@@ -122,6 +122,12 @@ impl<T: Debug> fmt::Display for Errors<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Errors<T> {
|
||||
pub fn num_errors(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// Reasons why a candidate might not be ready.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
|
||||
pub enum CandidateError {
|
||||
@@ -565,47 +571,30 @@ impl<T: SlotClock, E: EthSpec> BeaconNodeFallback<T, E> {
|
||||
F: Fn(BeaconNodeHttpClient) -> R,
|
||||
R: Future<Output = Result<O, Err>>,
|
||||
{
|
||||
let mut results = vec![];
|
||||
let mut to_retry = vec![];
|
||||
|
||||
// Run `func` using a `candidate`, returning the value or capturing errors.
|
||||
//
|
||||
// We use a macro instead of a closure here since it is not trivial to move `func` into a
|
||||
// closure.
|
||||
macro_rules! try_func {
|
||||
($candidate: ident) => {{
|
||||
inc_counter_vec(&ENDPOINT_REQUESTS, &[$candidate.beacon_node.as_ref()]);
|
||||
let run_on_candidate = |candidate: CandidateBeaconNode<E>| async {
|
||||
//inc_counter_vec(&ENDPOINT_REQUESTS, &[candidate.beacon_node.as_ref()]);
|
||||
|
||||
// There exists a race condition where `func` may be called when the candidate is
|
||||
// actually not ready. We deem this an acceptable inefficiency.
|
||||
match func($candidate.beacon_node.clone()).await {
|
||||
Ok(val) => results.push(Ok(val)),
|
||||
Err(e) => {
|
||||
results.push(Err((
|
||||
$candidate.beacon_node.to_string(),
|
||||
Error::RequestFailed(e),
|
||||
)));
|
||||
to_retry.push($candidate);
|
||||
inc_counter_vec(&ENDPOINT_ERRORS, &[$candidate.beacon_node.as_ref()]);
|
||||
}
|
||||
// There exists a race condition where `func` may be called when the candidate is
|
||||
// actually not ready. We deem this an acceptable inefficiency.
|
||||
match func(candidate.beacon_node.clone()).await {
|
||||
Ok(val) => Ok(val),
|
||||
Err(e) => {
|
||||
//inc_counter_vec(&ENDPOINT_ERRORS, &[candidate.beacon_node.as_ref()]);
|
||||
drop(candidate);
|
||||
Err(("Placeholder".to_string(), Error::RequestFailed(e)))
|
||||
//Err((candidate.beacon_node.to_string(), Error::RequestFailed(e)))
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
// First pass: try `func` on all candidates. Candidate order has already been set in
|
||||
// `update_all_candidates`. This ensures the most suitable node is always tried first.
|
||||
let candidates = self.candidates.read().await;
|
||||
for candidate in candidates.iter() {
|
||||
try_func!(candidate);
|
||||
}
|
||||
|
||||
if !to_retry.is_empty() {
|
||||
// Second pass. Some candidates did not return successfully. Try them again.
|
||||
// Errors will still be shown for a node if it required a retry.
|
||||
for candidate in to_retry.clone().iter() {
|
||||
try_func!(candidate);
|
||||
}
|
||||
};
|
||||
|
||||
// Run `func` on all candidates.
|
||||
let mut futures = vec![];
|
||||
let candidates = self.candidates.read().await.clone();
|
||||
for candidate in candidates.iter() {
|
||||
futures.push(run_on_candidate(candidate.clone()));
|
||||
}
|
||||
let results = future::join_all(futures).await;
|
||||
|
||||
let errors: Vec<_> = results.into_iter().filter_map(|res| res.err()).collect();
|
||||
|
||||
|
||||
@@ -304,105 +304,32 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
||||
)
|
||||
}
|
||||
|
||||
if self.validator_store.produce_block_v3() {
|
||||
for validator_pubkey in proposers {
|
||||
let builder_boost_factor = self.get_builder_boost_factor(&validator_pubkey);
|
||||
let service = self.clone();
|
||||
let log = log.clone();
|
||||
self.inner.context.executor.spawn(
|
||||
async move {
|
||||
let result = service
|
||||
.publish_block_v3(slot, validator_pubkey, builder_boost_factor)
|
||||
.await;
|
||||
for validator_pubkey in proposers {
|
||||
let builder_boost_factor = self.get_builder_boost_factor(&validator_pubkey);
|
||||
let service = self.clone();
|
||||
let log = log.clone();
|
||||
self.inner.context.executor.spawn(
|
||||
async move {
|
||||
let result = service
|
||||
.publish_block(slot, validator_pubkey, builder_boost_factor)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(_) => {}
|
||||
Err(BlockError::Recoverable(e)) | Err(BlockError::Irrecoverable(e)) => {
|
||||
error!(
|
||||
log,
|
||||
"Error whilst producing block";
|
||||
"error" => ?e,
|
||||
"block_slot" => ?slot,
|
||||
"info" => "block v3 proposal failed, this error may or may not result in a missed block"
|
||||
);
|
||||
}
|
||||
match result {
|
||||
Ok(_) => {}
|
||||
Err(BlockError::Recoverable(e)) | Err(BlockError::Irrecoverable(e)) => {
|
||||
error!(
|
||||
log,
|
||||
"Error whilst producing block";
|
||||
"error" => ?e,
|
||||
"block_slot" => ?slot,
|
||||
"info" => "block v3 proposal failed, this error may or may not result in a missed block"
|
||||
);
|
||||
}
|
||||
},
|
||||
"block service",
|
||||
)
|
||||
}
|
||||
} else {
|
||||
for validator_pubkey in proposers {
|
||||
let builder_proposals = self
|
||||
.validator_store
|
||||
.get_builder_proposals(&validator_pubkey);
|
||||
let service = self.clone();
|
||||
let log = log.clone();
|
||||
self.inner.context.executor.spawn(
|
||||
async move {
|
||||
if builder_proposals {
|
||||
let result = service
|
||||
.publish_block(slot, validator_pubkey, true)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Err(BlockError::Recoverable(e)) => {
|
||||
error!(
|
||||
log,
|
||||
"Error whilst producing block";
|
||||
"error" => ?e,
|
||||
"block_slot" => ?slot,
|
||||
"info" => "blinded proposal failed, attempting full block"
|
||||
);
|
||||
if let Err(e) = service
|
||||
.publish_block(slot, validator_pubkey, false)
|
||||
.await
|
||||
{
|
||||
// Log a `crit` since a full block
|
||||
// (non-builder) proposal failed.
|
||||
crit!(
|
||||
log,
|
||||
"Error whilst producing block";
|
||||
"error" => ?e,
|
||||
"block_slot" => ?slot,
|
||||
"info" => "full block attempted after a blinded failure",
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(BlockError::Irrecoverable(e)) => {
|
||||
// Only log an `error` since it's common for
|
||||
// builders to timeout on their response, only
|
||||
// to publish the block successfully themselves.
|
||||
error!(
|
||||
log,
|
||||
"Error whilst producing block";
|
||||
"error" => ?e,
|
||||
"block_slot" => ?slot,
|
||||
"info" => "this error may or may not result in a missed block",
|
||||
)
|
||||
}
|
||||
Ok(_) => {}
|
||||
};
|
||||
} else if let Err(e) = service
|
||||
.publish_block(slot, validator_pubkey, false)
|
||||
.await
|
||||
{
|
||||
// Log a `crit` since a full block (non-builder)
|
||||
// proposal failed.
|
||||
crit!(
|
||||
log,
|
||||
"Error whilst producing block";
|
||||
"message" => ?e,
|
||||
"block_slot" => ?slot,
|
||||
"info" => "proposal did not use a builder",
|
||||
);
|
||||
}
|
||||
},
|
||||
"block service",
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
"block service",
|
||||
)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -490,7 +417,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn publish_block_v3(
|
||||
async fn publish_block(
|
||||
self,
|
||||
slot: Slot,
|
||||
validator_pubkey: PublicKeyBytes,
|
||||
@@ -553,122 +480,32 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
||||
// Try the proposer nodes last, since it's likely that they don't have a
|
||||
// great view of attestations on the network.
|
||||
let unsigned_block = proposer_fallback
|
||||
.request_proposers_last(|beacon_node| async move {
|
||||
let _get_timer = metrics::start_timer_vec(
|
||||
&metrics::BLOCK_SERVICE_TIMES,
|
||||
&[metrics::BEACON_BLOCK_HTTP_GET],
|
||||
);
|
||||
let block_response = Self::get_validator_block_v3(
|
||||
&beacon_node,
|
||||
slot,
|
||||
randao_reveal_ref,
|
||||
graffiti,
|
||||
proposer_index,
|
||||
builder_boost_factor,
|
||||
log,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
BlockError::Recoverable(format!(
|
||||
"Error from beacon node when producing block: {:?}",
|
||||
e
|
||||
))
|
||||
});
|
||||
|
||||
Ok::<_, BlockError>(block_response)
|
||||
})
|
||||
.await??;
|
||||
|
||||
self_ref
|
||||
.sign_and_publish_block(
|
||||
proposer_fallback,
|
||||
slot,
|
||||
graffiti,
|
||||
&validator_pubkey,
|
||||
unsigned_block,
|
||||
.request_proposers_last(
|
||||
|beacon_node| async move {
|
||||
let _get_timer = metrics::start_timer_vec(
|
||||
&metrics::BLOCK_SERVICE_TIMES,
|
||||
&[metrics::BEACON_BLOCK_HTTP_GET],
|
||||
);
|
||||
Self::get_validator_block(
|
||||
&beacon_node,
|
||||
slot,
|
||||
randao_reveal_ref,
|
||||
graffiti,
|
||||
proposer_index,
|
||||
builder_boost_factor,
|
||||
log,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
BlockError::Recoverable(format!(
|
||||
"Error from beacon node when producing block: {:?}",
|
||||
e
|
||||
))
|
||||
})
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Produce a block at the given slot for validator_pubkey
|
||||
async fn publish_block(
|
||||
&self,
|
||||
slot: Slot,
|
||||
validator_pubkey: PublicKeyBytes,
|
||||
builder_proposal: bool,
|
||||
) -> Result<(), BlockError> {
|
||||
let log = self.context.log();
|
||||
let _timer =
|
||||
metrics::start_timer_vec(&metrics::BLOCK_SERVICE_TIMES, &[metrics::BEACON_BLOCK]);
|
||||
|
||||
let randao_reveal = match self
|
||||
.validator_store
|
||||
.randao_reveal(validator_pubkey, slot.epoch(E::slots_per_epoch()))
|
||||
.await
|
||||
{
|
||||
Ok(signature) => signature.into(),
|
||||
Err(ValidatorStoreError::UnknownPubkey(pubkey)) => {
|
||||
// A pubkey can be missing when a validator was recently removed
|
||||
// via the API.
|
||||
warn!(
|
||||
log,
|
||||
"Missing pubkey for block";
|
||||
"info" => "a validator may have recently been removed from this VC",
|
||||
"pubkey" => ?pubkey,
|
||||
"slot" => ?slot
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(BlockError::Recoverable(format!(
|
||||
"Unable to sign block: {:?}",
|
||||
e
|
||||
)))
|
||||
}
|
||||
};
|
||||
|
||||
let graffiti = determine_graffiti(
|
||||
&validator_pubkey,
|
||||
log,
|
||||
self.graffiti_file.clone(),
|
||||
self.validator_store.graffiti(&validator_pubkey),
|
||||
self.graffiti,
|
||||
);
|
||||
|
||||
let randao_reveal_ref = &randao_reveal;
|
||||
let self_ref = &self;
|
||||
let proposer_index = self.validator_store.validator_index(&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.
|
||||
//
|
||||
// Try the proposer nodes last, since it's likely that they don't have a
|
||||
// great view of attestations on the network.
|
||||
let unsigned_block = proposer_fallback
|
||||
.request_proposers_last(move |beacon_node| {
|
||||
Self::get_validator_block(
|
||||
beacon_node,
|
||||
slot,
|
||||
randao_reveal_ref,
|
||||
graffiti,
|
||||
proposer_index,
|
||||
builder_proposal,
|
||||
log,
|
||||
)
|
||||
})
|
||||
.await?;
|
||||
|
||||
self_ref
|
||||
.sign_and_publish_block(
|
||||
proposer_fallback,
|
||||
@@ -714,7 +551,7 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
||||
Ok::<_, BlockError>(())
|
||||
}
|
||||
|
||||
async fn get_validator_block_v3(
|
||||
async fn get_validator_block(
|
||||
beacon_node: &BeaconNodeHttpClient,
|
||||
slot: Slot,
|
||||
randao_reveal_ref: &SignatureBytes,
|
||||
@@ -757,65 +594,6 @@ impl<T: SlotClock + 'static, E: EthSpec> BlockService<T, E> {
|
||||
Ok::<_, BlockError>(unsigned_block)
|
||||
}
|
||||
|
||||
async fn get_validator_block(
|
||||
beacon_node: BeaconNodeHttpClient,
|
||||
slot: Slot,
|
||||
randao_reveal_ref: &SignatureBytes,
|
||||
graffiti: Option<Graffiti>,
|
||||
proposer_index: Option<u64>,
|
||||
builder_proposal: bool,
|
||||
log: &Logger,
|
||||
) -> Result<UnsignedBlock<E>, BlockError> {
|
||||
let unsigned_block = if !builder_proposal {
|
||||
let _get_timer = metrics::start_timer_vec(
|
||||
&metrics::BLOCK_SERVICE_TIMES,
|
||||
&[metrics::BEACON_BLOCK_HTTP_GET],
|
||||
);
|
||||
UnsignedBlock::Full(
|
||||
beacon_node
|
||||
.get_validator_blocks::<E>(slot, randao_reveal_ref, graffiti.as_ref())
|
||||
.await
|
||||
.map_err(|e| {
|
||||
BlockError::Recoverable(format!(
|
||||
"Error from beacon node when producing block: {:?}",
|
||||
e
|
||||
))
|
||||
})?
|
||||
.data,
|
||||
)
|
||||
} else {
|
||||
let _get_timer = metrics::start_timer_vec(
|
||||
&metrics::BLOCK_SERVICE_TIMES,
|
||||
&[metrics::BLINDED_BEACON_BLOCK_HTTP_GET],
|
||||
);
|
||||
UnsignedBlock::Blinded(
|
||||
beacon_node
|
||||
.get_validator_blinded_blocks::<E>(slot, randao_reveal_ref, graffiti.as_ref())
|
||||
.await
|
||||
.map_err(|e| {
|
||||
BlockError::Recoverable(format!(
|
||||
"Error from beacon node when producing block: {:?}",
|
||||
e
|
||||
))
|
||||
})?
|
||||
.data,
|
||||
)
|
||||
};
|
||||
|
||||
info!(
|
||||
log,
|
||||
"Received unsigned block";
|
||||
"slot" => slot.as_u64(),
|
||||
);
|
||||
if proposer_index != Some(unsigned_block.proposer_index()) {
|
||||
return Err(BlockError::Recoverable(
|
||||
"Proposer index does not match block proposer. Beacon chain re-orged".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok::<_, BlockError>(unsigned_block)
|
||||
}
|
||||
|
||||
/// Returns the builder boost factor of the given public key.
|
||||
/// The priority order for fetching this value is:
|
||||
///
|
||||
|
||||
@@ -170,10 +170,7 @@ pub fn cli_app() -> Command {
|
||||
.arg(
|
||||
Arg::new("produce-block-v3")
|
||||
.long("produce-block-v3")
|
||||
.help("Enable block production via the block v3 endpoint for this validator client. \
|
||||
This should only be enabled when paired with a beacon node \
|
||||
that has this endpoint implemented. This flag will be enabled by default in \
|
||||
future.")
|
||||
.help("This flag is deprecated and is no longer in use.")
|
||||
.action(ArgAction::SetTrue)
|
||||
.help_heading(FLAG_HEADER)
|
||||
.display_order(0)
|
||||
|
||||
@@ -84,8 +84,6 @@ pub struct Config {
|
||||
pub validator_registration_batch_size: usize,
|
||||
/// Enable slashing protection even while using web3signer keys.
|
||||
pub enable_web3signer_slashing_protection: bool,
|
||||
/// Enables block production via the block v3 endpoint. This configuration option can be removed post deneb.
|
||||
pub produce_block_v3: bool,
|
||||
/// Specifies the boost factor, a percentage multiplier to apply to the builder's payload value.
|
||||
pub builder_boost_factor: Option<u64>,
|
||||
/// If true, Lighthouse will prefer builder proposals, if available.
|
||||
@@ -136,7 +134,6 @@ impl Default for Config {
|
||||
enable_latency_measurement_service: true,
|
||||
validator_registration_batch_size: 500,
|
||||
enable_web3signer_slashing_protection: true,
|
||||
produce_block_v3: false,
|
||||
builder_boost_factor: None,
|
||||
prefer_builder_proposals: false,
|
||||
distributed: false,
|
||||
@@ -396,14 +393,18 @@ impl Config {
|
||||
config.builder_proposals = true;
|
||||
}
|
||||
|
||||
if cli_args.get_flag("produce-block-v3") {
|
||||
config.produce_block_v3 = true;
|
||||
}
|
||||
|
||||
if cli_args.get_flag("prefer-builder-proposals") {
|
||||
config.prefer_builder_proposals = true;
|
||||
}
|
||||
|
||||
if cli_args.get_flag("produce-block-v3") {
|
||||
warn!(
|
||||
log,
|
||||
"produce-block-v3 flag";
|
||||
"note" => "deprecated flag has no effect and should be removed"
|
||||
);
|
||||
}
|
||||
|
||||
config.gas_limit = cli_args
|
||||
.get_one::<String>("gas-limit")
|
||||
.map(|gas_limit| {
|
||||
|
||||
@@ -684,8 +684,8 @@ impl DoppelgangerService {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use environment::null_logger;
|
||||
use futures::executor::block_on;
|
||||
use logging::test_logger;
|
||||
use slot_clock::TestingSlotClock;
|
||||
use std::future;
|
||||
use std::time::Duration;
|
||||
@@ -729,7 +729,7 @@ mod test {
|
||||
fn build(self) -> TestScenario {
|
||||
let mut rng = XorShiftRng::from_seed([42; 16]);
|
||||
let slot_clock = TestingSlotClock::new(Slot::new(0), GENESIS_TIME, SLOT_DURATION);
|
||||
let log = null_logger().unwrap();
|
||||
let log = test_logger();
|
||||
|
||||
TestScenario {
|
||||
validators: (0..self.validator_count)
|
||||
|
||||
@@ -86,7 +86,8 @@ const _: () = assert!({
|
||||
/// This number is based upon `MIN_PEER_DISCOVERY_SLOT_LOOK_AHEAD` value in the
|
||||
/// `beacon_node::network::attestation_service` crate. It is not imported directly to avoid
|
||||
/// bringing in the entire crate.
|
||||
const _: () = assert!(ATTESTATION_SUBSCRIPTION_OFFSETS[0] > 2);
|
||||
const MIN_ATTESTATION_SUBSCRIPTION_LOOKAHEAD: u64 = 2;
|
||||
const _: () = assert!(ATTESTATION_SUBSCRIPTION_OFFSETS[0] > MIN_ATTESTATION_SUBSCRIPTION_LOOKAHEAD);
|
||||
|
||||
// The info in the enum variants is displayed in logging, clippy thinks it's dead code.
|
||||
#[derive(Debug)]
|
||||
@@ -121,6 +122,8 @@ pub struct DutyAndProof {
|
||||
pub struct SubscriptionSlots {
|
||||
/// Pairs of `(slot, already_sent)` in slot-descending order.
|
||||
slots: Vec<(Slot, AtomicBool)>,
|
||||
/// The slot of the duty itself.
|
||||
duty_slot: Slot,
|
||||
}
|
||||
|
||||
/// Create a selection proof for `duty`.
|
||||
@@ -172,18 +175,20 @@ impl SubscriptionSlots {
|
||||
.filter(|scheduled_slot| *scheduled_slot > current_slot)
|
||||
.map(|scheduled_slot| (scheduled_slot, AtomicBool::new(false)))
|
||||
.collect();
|
||||
Arc::new(Self { slots })
|
||||
Arc::new(Self { slots, duty_slot })
|
||||
}
|
||||
|
||||
/// Return `true` if we should send a subscription at `slot`.
|
||||
fn should_send_subscription_at(&self, slot: Slot) -> bool {
|
||||
// Iterate slots from smallest to largest looking for one that hasn't been completed yet.
|
||||
self.slots
|
||||
.iter()
|
||||
.rev()
|
||||
.any(|(scheduled_slot, already_sent)| {
|
||||
slot >= *scheduled_slot && !already_sent.load(Ordering::Relaxed)
|
||||
})
|
||||
slot + MIN_ATTESTATION_SUBSCRIPTION_LOOKAHEAD <= self.duty_slot
|
||||
&& self
|
||||
.slots
|
||||
.iter()
|
||||
.rev()
|
||||
.any(|(scheduled_slot, already_sent)| {
|
||||
slot >= *scheduled_slot && !already_sent.load(Ordering::Relaxed)
|
||||
})
|
||||
}
|
||||
|
||||
/// Update our record of subscribed slots to account for successful subscription at `slot`.
|
||||
@@ -733,26 +738,22 @@ async fn poll_beacon_attesters<T: SlotClock + 'static, E: EthSpec>(
|
||||
// If there are any subscriptions, push them out to beacon nodes
|
||||
if !subscriptions.is_empty() {
|
||||
let subscriptions_ref = &subscriptions;
|
||||
if let Err(e) = duties_service
|
||||
let subscription_result = duties_service
|
||||
.beacon_nodes
|
||||
.request(ApiTopic::Subscriptions, |beacon_node| async move {
|
||||
let _timer = metrics::start_timer_vec(
|
||||
&metrics::DUTIES_SERVICE_TIMES,
|
||||
&[metrics::SUBSCRIPTIONS_HTTP_POST],
|
||||
);
|
||||
beacon_node
|
||||
.post_validator_beacon_committee_subscriptions(subscriptions_ref)
|
||||
.await
|
||||
})
|
||||
.await
|
||||
{
|
||||
error!(
|
||||
log,
|
||||
"Failed to subscribe validators";
|
||||
"error" => %e
|
||||
.request(
|
||||
ApiTopic::Subscriptions,
|
||||
|beacon_node| async move {
|
||||
let _timer = metrics::start_timer_vec(
|
||||
&metrics::DUTIES_SERVICE_TIMES,
|
||||
&[metrics::SUBSCRIPTIONS_HTTP_POST],
|
||||
);
|
||||
beacon_node
|
||||
.post_validator_beacon_committee_subscriptions(subscriptions_ref)
|
||||
.await
|
||||
},
|
||||
)
|
||||
} else {
|
||||
// Record that subscriptions were successfully sent.
|
||||
.await;
|
||||
if subscription_result.as_ref().is_ok() {
|
||||
debug!(
|
||||
log,
|
||||
"Broadcast attestation subscriptions";
|
||||
@@ -761,6 +762,25 @@ async fn poll_beacon_attesters<T: SlotClock + 'static, E: EthSpec>(
|
||||
for subscription_slots in subscription_slots_to_confirm {
|
||||
subscription_slots.record_successful_subscription_at(current_slot);
|
||||
}
|
||||
} else if let Err(e) = subscription_result {
|
||||
if e.num_errors() < duties_service.beacon_nodes.num_total().await {
|
||||
warn!(
|
||||
log,
|
||||
"Some subscriptions failed";
|
||||
"error" => %e,
|
||||
);
|
||||
// If subscriptions were sent to at least one node, regard that as a success.
|
||||
// There is some redundancy built into the subscription schedule to handle failures.
|
||||
for subscription_slots in subscription_slots_to_confirm {
|
||||
subscription_slots.record_successful_subscription_at(current_slot);
|
||||
}
|
||||
} else {
|
||||
error!(
|
||||
log,
|
||||
"All subscriptions failed";
|
||||
"error" => %e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@ pub const PK_LEN: usize = 33;
|
||||
/// Provides convenience functions to ultimately provide:
|
||||
///
|
||||
/// - Verification of proof-of-knowledge of the public key in `self` for incoming HTTP requests,
|
||||
/// via the `Authorization` header.
|
||||
/// via the `Authorization` header.
|
||||
///
|
||||
/// The aforementioned scheme was first defined here:
|
||||
///
|
||||
/// https://github.com/sigp/lighthouse/issues/1269#issuecomment-649879855
|
||||
///
|
||||
///
|
||||
/// This scheme has since been tweaked to remove VC response signing and secp256k1 key generation.
|
||||
/// https://github.com/sigp/lighthouse/issues/5423
|
||||
pub struct ApiSecret {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use super::Context;
|
||||
use malloc_utils::scrape_allocator_metrics;
|
||||
use slot_clock::SlotClock;
|
||||
use std::sync::LazyLock;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use types::EthSpec;
|
||||
|
||||
@@ -11,7 +12,6 @@ pub const UNREGISTERED: &str = "unregistered";
|
||||
pub const FULL_UPDATE: &str = "full_update";
|
||||
pub const BEACON_BLOCK: &str = "beacon_block";
|
||||
pub const BEACON_BLOCK_HTTP_GET: &str = "beacon_block_http_get";
|
||||
pub const BLINDED_BEACON_BLOCK_HTTP_GET: &str = "blinded_beacon_block_http_get";
|
||||
pub const BEACON_BLOCK_HTTP_POST: &str = "beacon_block_http_post";
|
||||
pub const BLINDED_BEACON_BLOCK_HTTP_POST: &str = "blinded_beacon_block_http_post";
|
||||
pub const ATTESTATIONS: &str = "attestations";
|
||||
@@ -40,168 +40,233 @@ pub const WEB3SIGNER: &str = "web3signer";
|
||||
|
||||
pub use lighthouse_metrics::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref GENESIS_DISTANCE: Result<IntGauge> = try_create_int_gauge(
|
||||
pub static GENESIS_DISTANCE: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"vc_genesis_distance_seconds",
|
||||
"Distance between now and genesis time"
|
||||
);
|
||||
pub static ref ENABLED_VALIDATORS_COUNT: Result<IntGauge> = try_create_int_gauge(
|
||||
"Distance between now and genesis time",
|
||||
)
|
||||
});
|
||||
pub static ENABLED_VALIDATORS_COUNT: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"vc_validators_enabled_count",
|
||||
"Number of enabled validators"
|
||||
);
|
||||
pub static ref TOTAL_VALIDATORS_COUNT: Result<IntGauge> = try_create_int_gauge(
|
||||
"Number of enabled validators",
|
||||
)
|
||||
});
|
||||
pub static TOTAL_VALIDATORS_COUNT: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"vc_validators_total_count",
|
||||
"Number of total validators (enabled and disabled)"
|
||||
);
|
||||
"Number of total validators (enabled and disabled)",
|
||||
)
|
||||
});
|
||||
|
||||
pub static ref SIGNED_BLOCKS_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
pub static SIGNED_BLOCKS_TOTAL: LazyLock<Result<IntCounterVec>> = LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_beacon_blocks_total",
|
||||
"Total count of attempted block signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_ATTESTATIONS_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_ATTESTATIONS_TOTAL: LazyLock<Result<IntCounterVec>> = LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_attestations_total",
|
||||
"Total count of attempted Attestation signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_AGGREGATES_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_AGGREGATES_TOTAL: LazyLock<Result<IntCounterVec>> = LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_aggregates_total",
|
||||
"Total count of attempted SignedAggregateAndProof signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_SELECTION_PROOFS_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_SELECTION_PROOFS_TOTAL: LazyLock<Result<IntCounterVec>> = LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_selection_proofs_total",
|
||||
"Total count of attempted SelectionProof signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_SYNC_COMMITTEE_MESSAGES_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
"vc_signed_sync_committee_messages_total",
|
||||
"Total count of attempted SyncCommitteeMessage signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_SYNC_COMMITTEE_CONTRIBUTIONS_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
"vc_signed_sync_committee_contributions_total",
|
||||
"Total count of attempted ContributionAndProof signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_SYNC_SELECTION_PROOFS_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
"vc_signed_sync_selection_proofs_total",
|
||||
"Total count of attempted SyncSelectionProof signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_VOLUNTARY_EXITS_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_SYNC_COMMITTEE_MESSAGES_TOTAL: LazyLock<Result<IntCounterVec>> =
|
||||
LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_sync_committee_messages_total",
|
||||
"Total count of attempted SyncCommitteeMessage signings",
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_SYNC_COMMITTEE_CONTRIBUTIONS_TOTAL: LazyLock<Result<IntCounterVec>> =
|
||||
LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_sync_committee_contributions_total",
|
||||
"Total count of attempted ContributionAndProof signings",
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_SYNC_SELECTION_PROOFS_TOTAL: LazyLock<Result<IntCounterVec>> =
|
||||
LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_sync_selection_proofs_total",
|
||||
"Total count of attempted SyncSelectionProof signings",
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_VOLUNTARY_EXITS_TOTAL: LazyLock<Result<IntCounterVec>> = LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"vc_signed_voluntary_exits_total",
|
||||
"Total count of VoluntaryExit signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref SIGNED_VALIDATOR_REGISTRATIONS_TOTAL: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
"builder_validator_registrations_total",
|
||||
"Total count of ValidatorRegistrationData signings",
|
||||
&["status"]
|
||||
);
|
||||
pub static ref DUTIES_SERVICE_TIMES: Result<HistogramVec> = try_create_histogram_vec(
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static SIGNED_VALIDATOR_REGISTRATIONS_TOTAL: LazyLock<Result<IntCounterVec>> =
|
||||
LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"builder_validator_registrations_total",
|
||||
"Total count of ValidatorRegistrationData signings",
|
||||
&["status"],
|
||||
)
|
||||
});
|
||||
pub static DUTIES_SERVICE_TIMES: LazyLock<Result<HistogramVec>> = LazyLock::new(|| {
|
||||
try_create_histogram_vec(
|
||||
"vc_duties_service_task_times_seconds",
|
||||
"Duration to perform duties service tasks",
|
||||
&["task"]
|
||||
);
|
||||
pub static ref ATTESTATION_SERVICE_TIMES: Result<HistogramVec> = try_create_histogram_vec(
|
||||
&["task"],
|
||||
)
|
||||
});
|
||||
pub static ATTESTATION_SERVICE_TIMES: LazyLock<Result<HistogramVec>> = LazyLock::new(|| {
|
||||
try_create_histogram_vec(
|
||||
"vc_attestation_service_task_times_seconds",
|
||||
"Duration to perform attestation service tasks",
|
||||
&["task"]
|
||||
);
|
||||
pub static ref SLASHING_PROTECTION_PRUNE_TIMES: Result<Histogram> = try_create_histogram(
|
||||
&["task"],
|
||||
)
|
||||
});
|
||||
pub static SLASHING_PROTECTION_PRUNE_TIMES: LazyLock<Result<Histogram>> = LazyLock::new(|| {
|
||||
try_create_histogram(
|
||||
"vc_slashing_protection_prune_times_seconds",
|
||||
"Time required to prune the slashing protection DB",
|
||||
);
|
||||
pub static ref BLOCK_SERVICE_TIMES: Result<HistogramVec> = try_create_histogram_vec(
|
||||
)
|
||||
});
|
||||
pub static BLOCK_SERVICE_TIMES: LazyLock<Result<HistogramVec>> = LazyLock::new(|| {
|
||||
try_create_histogram_vec(
|
||||
"vc_beacon_block_service_task_times_seconds",
|
||||
"Duration to perform beacon block service tasks",
|
||||
&["task"]
|
||||
);
|
||||
pub static ref PROPOSER_COUNT: Result<IntGaugeVec> = try_create_int_gauge_vec(
|
||||
&["task"],
|
||||
)
|
||||
});
|
||||
pub static PROPOSER_COUNT: LazyLock<Result<IntGaugeVec>> = LazyLock::new(|| {
|
||||
try_create_int_gauge_vec(
|
||||
"vc_beacon_block_proposer_count",
|
||||
"Number of beacon block proposers on this host",
|
||||
&["task"]
|
||||
);
|
||||
pub static ref ATTESTER_COUNT: Result<IntGaugeVec> = try_create_int_gauge_vec(
|
||||
&["task"],
|
||||
)
|
||||
});
|
||||
pub static ATTESTER_COUNT: LazyLock<Result<IntGaugeVec>> = LazyLock::new(|| {
|
||||
try_create_int_gauge_vec(
|
||||
"vc_beacon_attester_count",
|
||||
"Number of attesters on this host",
|
||||
&["task"]
|
||||
);
|
||||
pub static ref PROPOSAL_CHANGED: Result<IntCounter> = try_create_int_counter(
|
||||
&["task"],
|
||||
)
|
||||
});
|
||||
pub static PROPOSAL_CHANGED: LazyLock<Result<IntCounter>> = LazyLock::new(|| {
|
||||
try_create_int_counter(
|
||||
"vc_beacon_block_proposal_changed",
|
||||
"A duties update discovered a new block proposer for the current slot",
|
||||
);
|
||||
/*
|
||||
* Endpoint metrics
|
||||
*/
|
||||
pub static ref ENDPOINT_ERRORS: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
)
|
||||
});
|
||||
/*
|
||||
* Endpoint metrics
|
||||
*/
|
||||
pub static ENDPOINT_ERRORS: LazyLock<Result<IntCounterVec>> = LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"bn_endpoint_errors",
|
||||
"The number of beacon node request errors for each endpoint",
|
||||
&["endpoint"]
|
||||
);
|
||||
pub static ref ENDPOINT_REQUESTS: Result<IntCounterVec> = try_create_int_counter_vec(
|
||||
&["endpoint"],
|
||||
)
|
||||
});
|
||||
pub static ENDPOINT_REQUESTS: LazyLock<Result<IntCounterVec>> = LazyLock::new(|| {
|
||||
try_create_int_counter_vec(
|
||||
"bn_endpoint_requests",
|
||||
"The number of beacon node requests for each endpoint",
|
||||
&["endpoint"]
|
||||
);
|
||||
&["endpoint"],
|
||||
)
|
||||
});
|
||||
|
||||
/*
|
||||
* Beacon node availability metrics
|
||||
*/
|
||||
pub static ref AVAILABLE_BEACON_NODES_COUNT: Result<IntGauge> = try_create_int_gauge(
|
||||
/*
|
||||
* Beacon node availability metrics
|
||||
*/
|
||||
pub static AVAILABLE_BEACON_NODES_COUNT: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"vc_beacon_nodes_available_count",
|
||||
"Number of available beacon nodes",
|
||||
);
|
||||
pub static ref SYNCED_BEACON_NODES_COUNT: Result<IntGauge> = try_create_int_gauge(
|
||||
)
|
||||
});
|
||||
pub static SYNCED_BEACON_NODES_COUNT: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"vc_beacon_nodes_synced_count",
|
||||
"Number of synced beacon nodes",
|
||||
);
|
||||
pub static ref TOTAL_BEACON_NODES_COUNT: Result<IntGauge> = try_create_int_gauge(
|
||||
)
|
||||
});
|
||||
pub static TOTAL_BEACON_NODES_COUNT: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"vc_beacon_nodes_total_count",
|
||||
"Total number of beacon nodes",
|
||||
);
|
||||
)
|
||||
});
|
||||
|
||||
pub static ref ETH2_FALLBACK_CONFIGURED: Result<IntGauge> = try_create_int_gauge(
|
||||
pub static ETH2_FALLBACK_CONFIGURED: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"sync_eth2_fallback_configured",
|
||||
"The number of configured eth2 fallbacks",
|
||||
);
|
||||
)
|
||||
});
|
||||
|
||||
pub static ref ETH2_FALLBACK_CONNECTED: Result<IntGauge> = try_create_int_gauge(
|
||||
pub static ETH2_FALLBACK_CONNECTED: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"sync_eth2_fallback_connected",
|
||||
"Set to 1 if connected to atleast one synced eth2 fallback node, otherwise set to 0",
|
||||
);
|
||||
/*
|
||||
* Signing Metrics
|
||||
*/
|
||||
pub static ref SIGNING_TIMES: Result<HistogramVec> = try_create_histogram_vec(
|
||||
)
|
||||
});
|
||||
/*
|
||||
* Signing Metrics
|
||||
*/
|
||||
pub static SIGNING_TIMES: LazyLock<Result<HistogramVec>> = LazyLock::new(|| {
|
||||
try_create_histogram_vec(
|
||||
"vc_signing_times_seconds",
|
||||
"Duration to obtain a signature",
|
||||
&["type"]
|
||||
);
|
||||
pub static ref BLOCK_SIGNING_TIMES: Result<Histogram> = try_create_histogram(
|
||||
&["type"],
|
||||
)
|
||||
});
|
||||
pub static BLOCK_SIGNING_TIMES: LazyLock<Result<Histogram>> = LazyLock::new(|| {
|
||||
try_create_histogram(
|
||||
"vc_block_signing_times_seconds",
|
||||
"Duration to obtain a signature for a block",
|
||||
);
|
||||
)
|
||||
});
|
||||
|
||||
pub static ref ATTESTATION_DUTY: Result<IntGaugeVec> = try_create_int_gauge_vec(
|
||||
pub static ATTESTATION_DUTY: LazyLock<Result<IntGaugeVec>> = LazyLock::new(|| {
|
||||
try_create_int_gauge_vec(
|
||||
"vc_attestation_duty_slot",
|
||||
"Attestation duty slot for all managed validators",
|
||||
&["validator"]
|
||||
);
|
||||
/*
|
||||
* BN latency
|
||||
*/
|
||||
pub static ref VC_BEACON_NODE_LATENCY: Result<HistogramVec> = try_create_histogram_vec(
|
||||
&["validator"],
|
||||
)
|
||||
});
|
||||
/*
|
||||
* BN latency
|
||||
*/
|
||||
pub static VC_BEACON_NODE_LATENCY: LazyLock<Result<HistogramVec>> = LazyLock::new(|| {
|
||||
try_create_histogram_vec(
|
||||
"vc_beacon_node_latency",
|
||||
"Round-trip latency for a simple API endpoint on each BN",
|
||||
&["endpoint"]
|
||||
);
|
||||
pub static ref VC_BEACON_NODE_LATENCY_PRIMARY_ENDPOINT: Result<Histogram> = try_create_histogram(
|
||||
"vc_beacon_node_latency_primary_endpoint",
|
||||
"Round-trip latency for the primary BN endpoint",
|
||||
);
|
||||
}
|
||||
&["endpoint"],
|
||||
)
|
||||
});
|
||||
pub static VC_BEACON_NODE_LATENCY_PRIMARY_ENDPOINT: LazyLock<Result<Histogram>> =
|
||||
LazyLock::new(|| {
|
||||
try_create_histogram(
|
||||
"vc_beacon_node_latency_primary_endpoint",
|
||||
"Round-trip latency for the primary BN endpoint",
|
||||
)
|
||||
});
|
||||
|
||||
pub fn gather_prometheus_metrics<E: EthSpec>(
|
||||
ctx: &Context<E>,
|
||||
|
||||
@@ -76,6 +76,7 @@ const WAITING_FOR_GENESIS_POLL_TIME: Duration = Duration::from_secs(12);
|
||||
/// This can help ensure that proper endpoint fallback occurs.
|
||||
const HTTP_ATTESTATION_TIMEOUT_QUOTIENT: u32 = 4;
|
||||
const HTTP_ATTESTER_DUTIES_TIMEOUT_QUOTIENT: u32 = 4;
|
||||
const HTTP_ATTESTATION_SUBSCRIPTIONS_TIMEOUT_QUOTIENT: u32 = 24;
|
||||
const HTTP_LIVENESS_TIMEOUT_QUOTIENT: u32 = 4;
|
||||
const HTTP_PROPOSAL_TIMEOUT_QUOTIENT: u32 = 2;
|
||||
const HTTP_PROPOSER_DUTIES_TIMEOUT_QUOTIENT: u32 = 4;
|
||||
@@ -324,6 +325,8 @@ impl<E: EthSpec> ProductionValidatorClient<E> {
|
||||
Timeouts {
|
||||
attestation: slot_duration / HTTP_ATTESTATION_TIMEOUT_QUOTIENT,
|
||||
attester_duties: slot_duration / HTTP_ATTESTER_DUTIES_TIMEOUT_QUOTIENT,
|
||||
attestation_subscriptions: slot_duration
|
||||
/ HTTP_ATTESTATION_SUBSCRIPTIONS_TIMEOUT_QUOTIENT,
|
||||
liveness: slot_duration / HTTP_LIVENESS_TIMEOUT_QUOTIENT,
|
||||
proposal: slot_duration / HTTP_PROPOSAL_TIMEOUT_QUOTIENT,
|
||||
proposer_duties: slot_duration / HTTP_PROPOSER_DUTIES_TIMEOUT_QUOTIENT,
|
||||
|
||||
@@ -71,7 +71,6 @@ pub struct ValidatorStore<T, E: EthSpec> {
|
||||
gas_limit: Option<u64>,
|
||||
builder_proposals: bool,
|
||||
enable_web3signer_slashing_protection: bool,
|
||||
produce_block_v3: bool,
|
||||
prefer_builder_proposals: bool,
|
||||
builder_boost_factor: Option<u64>,
|
||||
task_executor: TaskExecutor,
|
||||
@@ -106,7 +105,6 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
||||
gas_limit: config.gas_limit,
|
||||
builder_proposals: config.builder_proposals,
|
||||
enable_web3signer_slashing_protection: config.enable_web3signer_slashing_protection,
|
||||
produce_block_v3: config.produce_block_v3,
|
||||
prefer_builder_proposals: config.prefer_builder_proposals,
|
||||
builder_boost_factor: config.builder_boost_factor,
|
||||
task_executor,
|
||||
@@ -321,10 +319,6 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
||||
self.spec.fork_at_epoch(epoch)
|
||||
}
|
||||
|
||||
pub fn produce_block_v3(&self) -> bool {
|
||||
self.produce_block_v3
|
||||
}
|
||||
|
||||
/// Returns a `SigningMethod` for `validator_pubkey` *only if* that validator is considered safe
|
||||
/// by doppelganger protection.
|
||||
fn doppelganger_checked_signing_method(
|
||||
@@ -502,7 +496,7 @@ impl<T: SlotClock + 'static, E: EthSpec> ValidatorStore<T, E> {
|
||||
/// Translate the per validator `builder_proposals`, `builder_boost_factor` and
|
||||
/// `prefer_builder_proposals` to a boost factor, if available.
|
||||
/// - If `prefer_builder_proposals` is true, set boost factor to `u64::MAX` to indicate a
|
||||
/// preference for builder payloads.
|
||||
/// preference for builder payloads.
|
||||
/// - If `builder_boost_factor` is a value other than None, return its value as the boost factor.
|
||||
/// - If `builder_proposals` is set to false, set boost factor to 0 to indicate a preference for
|
||||
/// local payloads.
|
||||
|
||||
Reference in New Issue
Block a user