VC: avoid sending fee recipients until just before merge (#3064)
## Issue Addressed Presently if the VC is configured with a fee recipient it will error out when sending fee-recipient preparations to a beacon node that doesn't yet support the API: ``` Mar 08 22:23:36.236 ERRO Unable to publish proposer preparation error: All endpoints failed https://eth2-beacon-prater.infura.io/ => RequestFailed(StatusCode(404)), service: preparation ``` This doesn't affect other VC duties, but could be a source of anxiety for users trying to do the right thing and configure their fee recipients in advance. ## Proposed Changes Change the preparation service to only send preparations if the current slot is later than 2 epochs before the Bellatrix hard fork epoch. ## Additional Info I've tagged this v2.1.4 as I think it's a small change that's worth having for the next release
This commit is contained in:
parent
267d8babc8
commit
65eaf01942
@ -11,6 +11,9 @@ use std::sync::Arc;
|
|||||||
use tokio::time::{sleep, Duration};
|
use tokio::time::{sleep, Duration};
|
||||||
use types::{Address, ChainSpec, EthSpec, ProposerPreparationData};
|
use types::{Address, ChainSpec, EthSpec, ProposerPreparationData};
|
||||||
|
|
||||||
|
/// Number of epochs before the Bellatrix hard fork to begin posting proposer preparations.
|
||||||
|
const PROPOSER_PREPARATION_LOOKAHEAD_EPOCHS: u64 = 2;
|
||||||
|
|
||||||
/// Builds an `PreparationService`.
|
/// Builds an `PreparationService`.
|
||||||
pub struct PreparationServiceBuilder<T: SlotClock + 'static, E: EthSpec> {
|
pub struct PreparationServiceBuilder<T: SlotClock + 'static, E: EthSpec> {
|
||||||
validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
||||||
@ -122,15 +125,9 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationService<T, E> {
|
|||||||
let log = self.context.log().clone();
|
let log = self.context.log().clone();
|
||||||
|
|
||||||
let slot_duration = Duration::from_secs(spec.seconds_per_slot);
|
let slot_duration = Duration::from_secs(spec.seconds_per_slot);
|
||||||
let duration_to_next_epoch = self
|
|
||||||
.slot_clock
|
|
||||||
.duration_to_next_epoch(E::slots_per_epoch())
|
|
||||||
.ok_or("Unable to determine duration to next epoch")?;
|
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
log,
|
log,
|
||||||
"Proposer preparation service started";
|
"Proposer preparation service started";
|
||||||
"next_update_millis" => duration_to_next_epoch.as_millis()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let executor = self.context.executor.clone();
|
let executor = self.context.executor.clone();
|
||||||
@ -138,17 +135,19 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationService<T, E> {
|
|||||||
|
|
||||||
let interval_fut = async move {
|
let interval_fut = async move {
|
||||||
loop {
|
loop {
|
||||||
// Poll the endpoint immediately to ensure fee recipients are received.
|
if self.should_publish_at_current_slot(&spec) {
|
||||||
self.prepare_proposers_and_publish(&spec)
|
// Poll the endpoint immediately to ensure fee recipients are received.
|
||||||
.await
|
self.prepare_proposers_and_publish(&spec)
|
||||||
.map_err(|e| {
|
.await
|
||||||
error!(
|
.map_err(|e| {
|
||||||
log,
|
error!(
|
||||||
"Error during proposer preparation";
|
log,
|
||||||
"error" => format!("{:?}", e),
|
"Error during proposer preparation";
|
||||||
)
|
"error" => ?e,
|
||||||
})
|
)
|
||||||
.unwrap_or(());
|
})
|
||||||
|
.unwrap_or(());
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(duration_to_next_slot) = self.slot_clock.duration_to_next_slot() {
|
if let Some(duration_to_next_slot) = self.slot_clock.duration_to_next_slot() {
|
||||||
sleep(duration_to_next_slot).await;
|
sleep(duration_to_next_slot).await;
|
||||||
@ -164,6 +163,20 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationService<T, E> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the current slot is close to or past the Bellatrix fork epoch.
|
||||||
|
///
|
||||||
|
/// This avoids spamming the BN with preparations before the Bellatrix fork epoch, which may
|
||||||
|
/// cause errors if it doesn't support the preparation API.
|
||||||
|
fn should_publish_at_current_slot(&self, spec: &ChainSpec) -> bool {
|
||||||
|
let current_epoch = self
|
||||||
|
.slot_clock
|
||||||
|
.now()
|
||||||
|
.map_or(E::genesis_epoch(), |slot| slot.epoch(E::slots_per_epoch()));
|
||||||
|
spec.bellatrix_fork_epoch.map_or(false, |fork_epoch| {
|
||||||
|
current_epoch + PROPOSER_PREPARATION_LOOKAHEAD_EPOCHS >= fork_epoch
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepare proposer preparations and send to beacon node
|
/// Prepare proposer preparations and send to beacon node
|
||||||
async fn prepare_proposers_and_publish(&self, spec: &ChainSpec) -> Result<(), String> {
|
async fn prepare_proposers_and_publish(&self, spec: &ChainSpec) -> Result<(), String> {
|
||||||
let preparation_data = self.collect_preparation_data(spec);
|
let preparation_data = self.collect_preparation_data(spec);
|
||||||
|
Loading…
Reference in New Issue
Block a user