Allow per validator fee recipient via flag or file in validator client (similar to graffiti / graffiti-file) (#2924)

## Issue Addressed

#2883 

## Proposed Changes

* Added `suggested-fee-recipient` & `suggested-fee-recipient-file` flags to validator client (similar to graffiti / graffiti-file implementation).
* Added proposer preparation service to VC, which sends the fee-recipient of all known validators to the BN via [/eth/v1/validator/prepare_beacon_proposer](https://github.com/ethereum/beacon-APIs/pull/178) api once per slot
* Added [/eth/v1/validator/prepare_beacon_proposer](https://github.com/ethereum/beacon-APIs/pull/178) api endpoint and preparation data caching
* Added cleanup routine to remove cached proposer preparations when not updated for 2 epochs

## Additional Info

Changed the Implementation following the discussion in #2883.



Co-authored-by: pk910 <philipp@pk910.de>
Co-authored-by: Paul Hauner <paul@paulhauner.com>
Co-authored-by: Philipp K <philipp@pk910.de>
This commit is contained in:
Philipp K
2022-02-08 19:52:20 +00:00
parent d172c0b9fc
commit 5388183884
33 changed files with 1060 additions and 40 deletions

View File

@@ -5,10 +5,12 @@ mod check_synced;
mod cli;
mod config;
mod duties_service;
mod fee_recipient_file;
mod graffiti_file;
mod http_metrics;
mod key_cache;
mod notifier;
mod preparation_service;
mod signing_method;
mod sync_committee_service;
@@ -38,6 +40,7 @@ use eth2::{reqwest::ClientBuilder, BeaconNodeHttpClient, StatusCode, Timeouts};
use http_api::ApiSecret;
use notifier::spawn_notifier;
use parking_lot::RwLock;
use preparation_service::{PreparationService, PreparationServiceBuilder};
use reqwest::Certificate;
use slog::{error, info, warn, Logger};
use slot_clock::SlotClock;
@@ -82,6 +85,7 @@ pub struct ProductionValidatorClient<T: EthSpec> {
attestation_service: AttestationService<SystemTimeSlotClock, T>,
sync_committee_service: SyncCommitteeService<SystemTimeSlotClock, T>,
doppelganger_service: Option<Arc<DoppelgangerService>>,
preparation_service: PreparationService<SystemTimeSlotClock, T>,
validator_store: Arc<ValidatorStore<SystemTimeSlotClock, T>>,
http_api_listen_addr: Option<SocketAddr>,
config: Config,
@@ -406,6 +410,15 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
.runtime_context(context.service_context("attestation".into()))
.build()?;
let preparation_service = PreparationServiceBuilder::new()
.slot_clock(slot_clock.clone())
.validator_store(validator_store.clone())
.beacon_nodes(beacon_nodes.clone())
.runtime_context(context.service_context("preparation".into()))
.fee_recipient(config.fee_recipient)
.fee_recipient_file(config.fee_recipient_file.clone())
.build()?;
let sync_committee_service = SyncCommitteeService::new(
duties_service.clone(),
validator_store.clone(),
@@ -427,6 +440,7 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
attestation_service,
sync_committee_service,
doppelganger_service,
preparation_service,
validator_store,
config,
http_api_listen_addr: None,
@@ -458,6 +472,11 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
.start_update_service(&self.context.eth2_config.spec)
.map_err(|e| format!("Unable to start sync committee service: {}", e))?;
self.preparation_service
.clone()
.start_update_service(&self.context.eth2_config.spec)
.map_err(|e| format!("Unable to start preparation service: {}", e))?;
if let Some(doppelganger_service) = self.doppelganger_service.clone() {
DoppelgangerService::start_update_service(
doppelganger_service,