diff --git a/Cargo.lock b/Cargo.lock index 2978a3a19f6..ea992e989ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2235,23 +2235,6 @@ dependencies = [ "syn 2.0.89", ] -[[package]] -name = "doppelganger_service" -version = "0.1.0" -dependencies = [ - "beacon_node_fallback", - "environment", - "eth2", - "futures", - "logging", - "parking_lot 0.12.3", - "slog", - "slot_clock", - "task_executor", - "tokio", - "types", -] - [[package]] name = "dsl_auto_type" version = "0.1.2" @@ -9501,7 +9484,6 @@ dependencies = [ "clap_utils", "directory", "dirs", - "doppelganger_service", "environment", "eth2", "fdlimit", @@ -9554,7 +9536,6 @@ dependencies = [ "deposit_contract", "directory", "dirs", - "doppelganger_service", "eth2", "eth2_keystore", "ethereum_serde_utils", @@ -9646,7 +9627,6 @@ version = "0.1.0" dependencies = [ "beacon_node_fallback", "bls", - "doppelganger_service", "environment", "eth2", "futures", @@ -9667,8 +9647,12 @@ name = "validator_store" version = "0.1.0" dependencies = [ "account_utils", - "doppelganger_service", + "beacon_node_fallback", + "environment", + "eth2", + "futures", "initialized_validators", + "logging", "parking_lot 0.12.3", "serde", "signing_method", @@ -9676,6 +9660,7 @@ dependencies = [ "slog", "slot_clock", "task_executor", + "tokio", "types", "validator_metrics", ] diff --git a/Cargo.toml b/Cargo.toml index 9e921190b8f..bb2e96ac891 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,7 +84,6 @@ members = [ "validator_client", "validator_client/beacon_node_fallback", - "validator_client/doppelganger_service", "validator_client/graffiti_file", "validator_client/http_api", "validator_client/http_metrics", @@ -215,7 +214,6 @@ clap_utils = { path = "common/clap_utils" } compare_fields = { path = "common/compare_fields" } deposit_contract = { path = "common/deposit_contract" } directory = { path = "common/directory" } -doppelganger_service = { path = "validator_client/doppelganger_service" } validator_services = { path = "validator_client/validator_services" } environment = { path = "lighthouse/environment" } eth1 = { path = "beacon_node/eth1" } diff --git a/testing/web3signer_tests/src/lib.rs b/testing/web3signer_tests/src/lib.rs index bebc8fa13be..4099d80f687 100644 --- a/testing/web3signer_tests/src/lib.rs +++ b/testing/web3signer_tests/src/lib.rs @@ -307,7 +307,7 @@ mod tests { /// A testing rig which holds a `ValidatorStore`. struct ValidatorStoreRig { - validator_store: Arc>, + validator_store: Arc>, _validator_dir: TempDir, runtime: Arc, _runtime_shutdown: async_channel::Sender<()>, @@ -361,7 +361,7 @@ mod tests { ..Default::default() }; - let validator_store = ValidatorStore::<_, E>::new( + let validator_store = ValidatorStore::<_>::new( initialized_validators, slashing_protection, Hash256::repeat_byte(42), @@ -370,6 +370,7 @@ mod tests { slot_clock, &config, executor, + E::slots_per_epoch(), log.clone(), ); @@ -486,7 +487,7 @@ mod tests { generate_sig: F, ) -> Self where - F: Fn(PublicKeyBytes, Arc>) -> R, + F: Fn(PublicKeyBytes, Arc>) -> R, R: Future, // We use the `SignedObject` trait to white-list objects for comparison. This avoids // accidentally comparing something meaningless like a `()`. @@ -521,7 +522,7 @@ mod tests { web3signer_should_sign: bool, ) -> Self where - F: Fn(PublicKeyBytes, Arc>) -> R, + F: Fn(PublicKeyBytes, Arc>) -> R, R: Future>, { for validator_rig in &self.validator_rigs { @@ -588,7 +589,7 @@ mod tests { .await .assert_signatures_match("randao_reveal", |pubkey, validator_store| async move { validator_store - .randao_reveal(pubkey, Epoch::new(0)) + .randao_reveal::(pubkey, Epoch::new(0)) .await .unwrap() }) @@ -629,7 +630,7 @@ mod tests { .await .assert_signatures_match("selection_proof", |pubkey, validator_store| async move { validator_store - .produce_selection_proof(pubkey, Slot::new(0)) + .produce_selection_proof::(pubkey, Slot::new(0)) .await .unwrap() }) @@ -639,7 +640,7 @@ mod tests { |pubkey, validator_store| async move { let val_reg_data = get_validator_registration(pubkey); validator_store - .sign_validator_registration_data(val_reg_data) + .sign_validator_registration_data::(val_reg_data) .await .unwrap() }, @@ -679,7 +680,11 @@ mod tests { "sync_selection_proof", |pubkey, validator_store| async move { validator_store - .produce_sync_selection_proof(&pubkey, altair_fork_slot, SyncSubnetId::from(0)) + .produce_sync_selection_proof::( + &pubkey, + altair_fork_slot, + SyncSubnetId::from(0), + ) .await .unwrap() }, @@ -689,7 +694,12 @@ mod tests { "sync_committee_signature", |pubkey, validator_store| async move { validator_store - .produce_sync_committee_signature(altair_fork_slot, Hash256::zero(), 0, &pubkey) + .produce_sync_committee_signature::( + altair_fork_slot, + Hash256::zero(), + 0, + &pubkey, + ) .await .unwrap() }, @@ -722,7 +732,7 @@ mod tests { |pubkey, validator_store| async move { let val_reg_data = get_validator_registration(pubkey); validator_store - .sign_validator_registration_data(val_reg_data) + .sign_validator_registration_data::(val_reg_data) .await .unwrap() }, diff --git a/validator_client/Cargo.toml b/validator_client/Cargo.toml index 044a622d544..582a44b6f72 100644 --- a/validator_client/Cargo.toml +++ b/validator_client/Cargo.toml @@ -17,7 +17,6 @@ beacon_node_fallback = { workspace = true } clap = { workspace = true } clap_utils = { workspace = true } directory = { workspace = true } -doppelganger_service = { workspace = true } dirs = { workspace = true } eth2 = { workspace = true } environment = { workspace = true } diff --git a/validator_client/beacon_node_fallback/src/lib.rs b/validator_client/beacon_node_fallback/src/lib.rs index 95a221f1897..b8223cbfcda 100644 --- a/validator_client/beacon_node_fallback/src/lib.rs +++ b/validator_client/beacon_node_fallback/src/lib.rs @@ -17,7 +17,6 @@ use std::cmp::Ordering; use std::fmt; use std::fmt::Debug; use std::future::Future; -use std::marker::PhantomData; use std::sync::Arc; use std::time::{Duration, Instant}; use strum::{EnumString, EnumVariantNames}; @@ -60,7 +59,7 @@ pub struct LatencyMeasurement { /// See `SLOT_LOOKAHEAD` for information about when this should run. pub fn start_fallback_updater_service( context: RuntimeContext, - beacon_nodes: Arc>, + beacon_nodes: Arc>, ) -> Result<(), &'static str> { let executor = context.executor; if beacon_nodes.slot_clock.is_none() { @@ -69,7 +68,7 @@ pub fn start_fallback_updater_service( let future = async move { loop { - beacon_nodes.update_all_candidates().await; + beacon_nodes.update_all_candidates::().await; let sleep_time = beacon_nodes .slot_clock @@ -184,29 +183,27 @@ impl Serialize for CandidateInfo { /// Represents a `BeaconNodeHttpClient` inside a `BeaconNodeFallback` that may or may not be used /// for a query. #[derive(Clone, Debug)] -pub struct CandidateBeaconNode { +pub struct CandidateBeaconNode { pub index: usize, pub beacon_node: BeaconNodeHttpClient, pub health: Arc>>, - _phantom: PhantomData, } -impl PartialEq for CandidateBeaconNode { +impl PartialEq for CandidateBeaconNode { fn eq(&self, other: &Self) -> bool { self.index == other.index && self.beacon_node == other.beacon_node } } -impl Eq for CandidateBeaconNode {} +impl Eq for CandidateBeaconNode {} -impl CandidateBeaconNode { +impl CandidateBeaconNode { /// Instantiate a new node. pub fn new(beacon_node: BeaconNodeHttpClient, index: usize) -> Self { Self { index, beacon_node, health: Arc::new(RwLock::new(Err(CandidateError::Uninitialized))), - _phantom: PhantomData, } } @@ -215,14 +212,14 @@ impl CandidateBeaconNode { *self.health.read().await } - pub async fn refresh_health( + pub async fn refresh_health( &self, distance_tiers: &BeaconNodeSyncDistanceTiers, slot_clock: Option<&T>, spec: &ChainSpec, log: &Logger, ) -> Result<(), CandidateError> { - if let Err(e) = self.is_compatible(spec, log).await { + if let Err(e) = self.is_compatible::(spec, log).await { *self.health.write().await = Err(e); return Err(e); } @@ -286,7 +283,11 @@ impl CandidateBeaconNode { } /// Checks if the node has the correct specification. - async fn is_compatible(&self, spec: &ChainSpec, log: &Logger) -> Result<(), CandidateError> { + async fn is_compatible( + &self, + spec: &ChainSpec, + log: &Logger, + ) -> Result<(), CandidateError> { let config = self .beacon_node .get_config_spec::() @@ -371,8 +372,8 @@ impl CandidateBeaconNode { /// behaviour, where the failure of one candidate results in the next candidate receiving an /// identical query. #[derive(Clone, Debug)] -pub struct BeaconNodeFallback { - pub candidates: Arc>>>, +pub struct BeaconNodeFallback { + pub candidates: Arc>>, distance_tiers: BeaconNodeSyncDistanceTiers, slot_clock: Option, broadcast_topics: Vec, @@ -380,9 +381,9 @@ pub struct BeaconNodeFallback { log: Logger, } -impl BeaconNodeFallback { +impl BeaconNodeFallback { pub fn new( - candidates: Vec>, + candidates: Vec, config: Config, broadcast_topics: Vec, spec: Arc, @@ -466,7 +467,7 @@ impl BeaconNodeFallback { /// It is possible for a node to return an unsynced status while continuing to serve /// low quality responses. To route around this it's best to poll all connected beacon nodes. /// A previous implementation of this function polled only the unavailable BNs. - pub async fn update_all_candidates(&self) { + pub async fn update_all_candidates(&self) { // Clone the vec, so we release the read lock immediately. // `candidate.health` is behind an Arc, so this would still allow us to mutate the values. let candidates = self.candidates.read().await.clone(); @@ -474,7 +475,7 @@ impl BeaconNodeFallback { let mut nodes = Vec::with_capacity(candidates.len()); for candidate in candidates.iter() { - futures.push(candidate.refresh_health( + futures.push(candidate.refresh_health::( &self.distance_tiers, self.slot_clock.as_ref(), &self.spec, @@ -693,7 +694,7 @@ impl BeaconNodeFallback { } /// Helper functions to allow sorting candidate nodes by health. -async fn sort_nodes_by_health(nodes: &mut Vec>) { +async fn sort_nodes_by_health(nodes: &mut Vec) { // Fetch all health values. let health_results: Vec> = future::join_all(nodes.iter().map(|node| node.health())).await; @@ -711,7 +712,7 @@ async fn sort_nodes_by_health(nodes: &mut Vec }); // Reorder candidates based on the sorted indices. - let sorted_nodes: Vec> = indices_with_health + let sorted_nodes: Vec = indices_with_health .into_iter() .map(|(index, _)| nodes[index].clone()) .collect(); @@ -743,9 +744,7 @@ mod tests { use eth2::Timeouts; use std::str::FromStr; use strum::VariantNames; - use types::{MainnetEthSpec, Slot}; - - type E = MainnetEthSpec; + use types::Slot; #[test] fn api_topic_all() { @@ -764,7 +763,7 @@ mod tests { let optimistic_status = IsOptimistic::No; let execution_status = ExecutionEngineHealth::Healthy; - fn new_candidate(index: usize) -> CandidateBeaconNode { + fn new_candidate(index: usize) -> CandidateBeaconNode { let beacon_node = BeaconNodeHttpClient::new( SensitiveUrl::parse(&format!("http://example_{index}.com")).unwrap(), Timeouts::set_all(Duration::from_secs(index as u64)), diff --git a/validator_client/doppelganger_service/Cargo.toml b/validator_client/doppelganger_service/Cargo.toml deleted file mode 100644 index e5f7d3f2ba2..00000000000 --- a/validator_client/doppelganger_service/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "doppelganger_service" -version = "0.1.0" -edition = { workspace = true } -authors = ["Sigma Prime "] - -[dependencies] -beacon_node_fallback = { workspace = true } -environment = { workspace = true } -eth2 = { workspace = true } -parking_lot = { workspace = true } -slog = { workspace = true } -slot_clock = { workspace = true } -task_executor = { workspace = true } -tokio = { workspace = true } -types = { workspace = true } - -[dev-dependencies] -futures = { workspace = true } -logging = {workspace = true } diff --git a/validator_client/http_api/Cargo.toml b/validator_client/http_api/Cargo.toml index 96c836f6f3a..92cd631e3b0 100644 --- a/validator_client/http_api/Cargo.toml +++ b/validator_client/http_api/Cargo.toml @@ -14,7 +14,6 @@ bls = { workspace = true } beacon_node_fallback = { workspace = true } deposit_contract = { workspace = true } directory = { workspace = true } -doppelganger_service = { workspace = true } dirs = { workspace = true } graffiti_file = { workspace = true } eth2 = { workspace = true } diff --git a/validator_client/http_api/src/create_signed_voluntary_exit.rs b/validator_client/http_api/src/create_signed_voluntary_exit.rs index 32269b202b0..3c9a9138566 100644 --- a/validator_client/http_api/src/create_signed_voluntary_exit.rs +++ b/validator_client/http_api/src/create_signed_voluntary_exit.rs @@ -9,7 +9,7 @@ use validator_store::ValidatorStore; pub async fn create_signed_voluntary_exit( pubkey: PublicKey, maybe_epoch: Option, - validator_store: Arc>, + validator_store: Arc>, slot_clock: T, log: Logger, ) -> Result, warp::Rejection> { @@ -52,7 +52,7 @@ pub async fn create_signed_voluntary_exit(pubkey_bytes, voluntary_exit) .await .map_err(|e| { warp_utils::reject::custom_server_error(format!( diff --git a/validator_client/http_api/src/create_validator.rs b/validator_client/http_api/src/create_validator.rs index f90a1057a43..43c2b34d890 100644 --- a/validator_client/http_api/src/create_validator.rs +++ b/validator_client/http_api/src/create_validator.rs @@ -8,7 +8,6 @@ use eth2::lighthouse_vc::types::{self as api_types}; use slot_clock::SlotClock; use std::path::{Path, PathBuf}; use types::ChainSpec; -use types::EthSpec; use validator_dir::{keystore_password_path, Builder as ValidatorDirBuilder}; use validator_store::ValidatorStore; use zeroize::Zeroizing; @@ -24,13 +23,13 @@ use zeroize::Zeroizing; /// /// If `key_derivation_path_offset` is supplied then the EIP-2334 validator index will start at /// this point. -pub async fn create_validators_mnemonic, T: 'static + SlotClock, E: EthSpec>( +pub async fn create_validators_mnemonic, T: 'static + SlotClock>( mnemonic_opt: Option, key_derivation_path_offset: Option, validator_requests: &[api_types::ValidatorRequest], validator_dir: P, secrets_dir: Option, - validator_store: &ValidatorStore, + validator_store: &ValidatorStore, spec: &ChainSpec, ) -> Result<(Vec, Mnemonic), warp::Rejection> { let mnemonic = mnemonic_opt.unwrap_or_else(random_mnemonic); @@ -176,9 +175,9 @@ pub async fn create_validators_mnemonic, T: 'static + SlotClock, Ok((validators, mnemonic)) } -pub async fn create_validators_web3signer( +pub async fn create_validators_web3signer( validators: Vec, - validator_store: &ValidatorStore, + validator_store: &ValidatorStore, ) -> Result<(), warp::Rejection> { for validator in validators { validator_store diff --git a/validator_client/http_api/src/graffiti.rs b/validator_client/http_api/src/graffiti.rs index 86238a697c6..ee7cf1e505d 100644 --- a/validator_client/http_api/src/graffiti.rs +++ b/validator_client/http_api/src/graffiti.rs @@ -1,12 +1,12 @@ use bls::PublicKey; use slot_clock::SlotClock; use std::sync::Arc; -use types::{graffiti::GraffitiString, EthSpec, Graffiti}; +use types::{graffiti::GraffitiString, Graffiti}; use validator_store::ValidatorStore; -pub fn get_graffiti( +pub fn get_graffiti( validator_pubkey: PublicKey, - validator_store: Arc>, + validator_store: Arc>, graffiti_flag: Option, ) -> Result { let initialized_validators_rw_lock = validator_store.initialized_validators(); @@ -26,10 +26,10 @@ pub fn get_graffiti( } } -pub fn set_graffiti( +pub fn set_graffiti( validator_pubkey: PublicKey, graffiti: GraffitiString, - validator_store: Arc>, + validator_store: Arc>, ) -> Result<(), warp::Rejection> { let initialized_validators_rw_lock = validator_store.initialized_validators(); let mut initialized_validators = initialized_validators_rw_lock.write(); @@ -53,9 +53,9 @@ pub fn set_graffiti( } } -pub fn delete_graffiti( +pub fn delete_graffiti( validator_pubkey: PublicKey, - validator_store: Arc>, + validator_store: Arc>, ) -> Result<(), warp::Rejection> { let initialized_validators_rw_lock = validator_store.initialized_validators(); let mut initialized_validators = initialized_validators_rw_lock.write(); diff --git a/validator_client/http_api/src/keystores.rs b/validator_client/http_api/src/keystores.rs index fd6b4fdae51..5cd47b9ac20 100644 --- a/validator_client/http_api/src/keystores.rs +++ b/validator_client/http_api/src/keystores.rs @@ -17,15 +17,15 @@ use std::path::PathBuf; use std::sync::Arc; use task_executor::TaskExecutor; use tokio::runtime::Handle; -use types::{EthSpec, PublicKeyBytes}; +use types::PublicKeyBytes; use validator_dir::{keystore_password_path, Builder as ValidatorDirBuilder}; use validator_store::ValidatorStore; use warp::Rejection; use warp_utils::reject::{custom_bad_request, custom_server_error}; use zeroize::Zeroizing; -pub fn list( - validator_store: Arc>, +pub fn list( + validator_store: Arc>, ) -> ListKeystoresResponse { let initialized_validators_rwlock = validator_store.initialized_validators(); let initialized_validators = initialized_validators_rwlock.read(); @@ -58,11 +58,11 @@ pub fn list( ListKeystoresResponse { data: keystores } } -pub fn import( +pub fn import( request: ImportKeystoresRequest, validator_dir: PathBuf, secrets_dir: Option, - validator_store: Arc>, + validator_store: Arc>, task_executor: TaskExecutor, log: Logger, ) -> Result { @@ -122,7 +122,7 @@ pub fn import( ) } else if let Some(handle) = task_executor.handle() { // Import the keystore. - match import_single_keystore( + match import_single_keystore::( keystore, password, validator_dir.clone(), @@ -166,12 +166,12 @@ pub fn import( Ok(ImportKeystoresResponse { data: statuses }) } -fn import_single_keystore( +fn import_single_keystore( keystore: Keystore, password: Zeroizing, validator_dir_path: PathBuf, secrets_dir: Option, - validator_store: &ValidatorStore, + validator_store: &ValidatorStore, handle: Handle, ) -> Result { // Check if the validator key already exists, erroring if it is a remote signer validator. @@ -239,9 +239,9 @@ fn import_single_keystore( Ok(ImportKeystoreStatus::Imported) } -pub fn delete( +pub fn delete( request: DeleteKeystoresRequest, - validator_store: Arc>, + validator_store: Arc>, task_executor: TaskExecutor, log: Logger, ) -> Result { @@ -272,9 +272,9 @@ pub fn delete( }) } -pub fn export( +pub fn export( request: DeleteKeystoresRequest, - validator_store: Arc>, + validator_store: Arc>, task_executor: TaskExecutor, log: Logger, ) -> Result { diff --git a/validator_client/http_api/src/lib.rs b/validator_client/http_api/src/lib.rs index f3dab3780c0..d0ec238db76 100644 --- a/validator_client/http_api/src/lib.rs +++ b/validator_client/http_api/src/lib.rs @@ -40,7 +40,6 @@ use slog::{crit, info, warn, Logger}; use slot_clock::SlotClock; use std::collections::HashMap; use std::future::Future; -use std::marker::PhantomData; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::PathBuf; use std::sync::Arc; @@ -79,7 +78,7 @@ pub struct Context { pub task_executor: TaskExecutor, pub api_secret: ApiSecret, pub block_service: Option>, - pub validator_store: Option>>, + pub validator_store: Option>>, pub validator_dir: Option, pub secrets_dir: Option, pub graffiti_file: Option, @@ -89,7 +88,6 @@ pub struct Context { pub log: Logger, pub sse_logging_components: Option, pub slot_clock: T, - pub _phantom: PhantomData, } /// Configuration for the HTTP server. @@ -323,7 +321,7 @@ pub fn serve( .and(warp::path("validators")) .and(warp::path::end()) .and(validator_store_filter.clone()) - .then(|validator_store: Arc>| { + .then(|validator_store: Arc>| { blocking_json_task(move || { let validators = validator_store .initialized_validators() @@ -348,7 +346,7 @@ pub fn serve( .and(warp::path::end()) .and(validator_store_filter.clone()) .then( - |validator_pubkey: PublicKey, validator_store: Arc>| { + |validator_pubkey: PublicKey, validator_store: Arc>| { blocking_json_task(move || { let validator = validator_store .initialized_validators() @@ -399,7 +397,7 @@ pub fn serve( .and(graffiti_flag_filter) .and(log_filter.clone()) .then( - |validator_store: Arc>, + |validator_store: Arc>, graffiti_file: Option, graffiti_flag: Option, log| { @@ -472,7 +470,7 @@ pub fn serve( move |body: Vec, validator_dir: PathBuf, secrets_dir: PathBuf, - validator_store: Arc>, + validator_store: Arc>, spec: Arc, task_executor: TaskExecutor| { blocking_json_task(move || { @@ -517,7 +515,7 @@ pub fn serve( move |body: api_types::CreateValidatorsMnemonicRequest, validator_dir: PathBuf, secrets_dir: PathBuf, - validator_store: Arc>, + validator_store: Arc>, spec: Arc, task_executor: TaskExecutor| { blocking_json_task(move || { @@ -564,7 +562,7 @@ pub fn serve( move |body: api_types::KeystoreValidatorsPostRequest, validator_dir: PathBuf, secrets_dir: PathBuf, - validator_store: Arc>, + validator_store: Arc>, task_executor: TaskExecutor| { blocking_json_task(move || { // Check to ensure the password is correct. @@ -650,7 +648,7 @@ pub fn serve( .and(task_executor_filter.clone()) .then( |body: Vec, - validator_store: Arc>, + validator_store: Arc>, task_executor: TaskExecutor| { blocking_json_task(move || { if let Some(handle) = task_executor.handle() { @@ -704,7 +702,7 @@ pub fn serve( .then( |validator_pubkey: PublicKey, body: api_types::ValidatorPatchRequest, - validator_store: Arc>, + validator_store: Arc>, graffiti_file: Option, task_executor: TaskExecutor| { blocking_json_task(move || { @@ -858,7 +856,7 @@ pub fn serve( .and(warp::path::end()) .and(validator_store_filter.clone()) .then( - |validator_pubkey: PublicKey, validator_store: Arc>| { + |validator_pubkey: PublicKey, validator_store: Arc>| { blocking_json_task(move || { if validator_store .initialized_validators() @@ -899,7 +897,7 @@ pub fn serve( .then( |validator_pubkey: PublicKey, request: api_types::UpdateFeeRecipientRequest, - validator_store: Arc>| { + validator_store: Arc>| { blocking_json_task(move || { if validator_store .initialized_validators() @@ -935,7 +933,7 @@ pub fn serve( .and(warp::path::end()) .and(validator_store_filter.clone()) .then( - |validator_pubkey: PublicKey, validator_store: Arc>| { + |validator_pubkey: PublicKey, validator_store: Arc>| { blocking_json_task(move || { if validator_store .initialized_validators() @@ -971,7 +969,7 @@ pub fn serve( .and(warp::path::end()) .and(validator_store_filter.clone()) .then( - |validator_pubkey: PublicKey, validator_store: Arc>| { + |validator_pubkey: PublicKey, validator_store: Arc>| { blocking_json_task(move || { if validator_store .initialized_validators() @@ -1004,7 +1002,7 @@ pub fn serve( .then( |validator_pubkey: PublicKey, request: api_types::UpdateGasLimitRequest, - validator_store: Arc>| { + validator_store: Arc>| { blocking_json_task(move || { if validator_store .initialized_validators() @@ -1040,7 +1038,7 @@ pub fn serve( .and(warp::path::end()) .and(validator_store_filter.clone()) .then( - |validator_pubkey: PublicKey, validator_store: Arc>| { + |validator_pubkey: PublicKey, validator_store: Arc>| { blocking_json_task(move || { if validator_store .initialized_validators() @@ -1082,14 +1080,14 @@ pub fn serve( .then( |pubkey: PublicKey, query: api_types::VoluntaryExitQuery, - validator_store: Arc>, + validator_store: Arc>, slot_clock: T, log, task_executor: TaskExecutor| { blocking_json_task(move || { if let Some(handle) = task_executor.handle() { let signed_voluntary_exit = - handle.block_on(create_signed_voluntary_exit( + handle.block_on(create_signed_voluntary_exit::( pubkey, query.epoch, validator_store, @@ -1116,7 +1114,7 @@ pub fn serve( .and(graffiti_flag_filter) .then( |pubkey: PublicKey, - validator_store: Arc>, + validator_store: Arc>, graffiti_flag: Option| { blocking_json_task(move || { let graffiti = get_graffiti(pubkey.clone(), validator_store, graffiti_flag)?; @@ -1140,7 +1138,7 @@ pub fn serve( .then( |pubkey: PublicKey, query: SetGraffitiRequest, - validator_store: Arc>, + validator_store: Arc>, graffiti_file: Option| { blocking_json_task(move || { if graffiti_file.is_some() { @@ -1165,7 +1163,7 @@ pub fn serve( .and(graffiti_file_filter.clone()) .then( |pubkey: PublicKey, - validator_store: Arc>, + validator_store: Arc>, graffiti_file: Option| { blocking_json_task(move || { if graffiti_file.is_some() { @@ -1182,7 +1180,7 @@ pub fn serve( // GET /eth/v1/keystores let get_std_keystores = std_keystores.and(validator_store_filter.clone()).then( - |validator_store: Arc>| { + |validator_store: Arc>| { blocking_json_task(move || Ok(keystores::list(validator_store))) }, ); @@ -1225,7 +1223,7 @@ pub fn serve( // GET /eth/v1/remotekeys let get_std_remotekeys = std_remotekeys.and(validator_store_filter.clone()).then( - |validator_store: Arc>| { + |validator_store: Arc>| { blocking_json_task(move || Ok(remotekeys::list(validator_store))) }, ); diff --git a/validator_client/http_api/src/remotekeys.rs b/validator_client/http_api/src/remotekeys.rs index 289be571825..5bcee7a9ad7 100644 --- a/validator_client/http_api/src/remotekeys.rs +++ b/validator_client/http_api/src/remotekeys.rs @@ -13,14 +13,14 @@ use slot_clock::SlotClock; use std::sync::Arc; use task_executor::TaskExecutor; use tokio::runtime::Handle; -use types::{EthSpec, PublicKeyBytes}; +use types::PublicKeyBytes; use url::Url; use validator_store::ValidatorStore; use warp::Rejection; use warp_utils::reject::custom_server_error; -pub fn list( - validator_store: Arc>, +pub fn list( + validator_store: Arc>, ) -> ListRemotekeysResponse { let initialized_validators_rwlock = validator_store.initialized_validators(); let initialized_validators = initialized_validators_rwlock.read(); @@ -48,9 +48,9 @@ pub fn list( ListRemotekeysResponse { data: keystores } } -pub fn import( +pub fn import( request: ImportRemotekeysRequest, - validator_store: Arc>, + validator_store: Arc>, task_executor: TaskExecutor, log: Logger, ) -> Result { @@ -89,10 +89,10 @@ pub fn import( Ok(ImportRemotekeysResponse { data: statuses }) } -fn import_single_remotekey( +fn import_single_remotekey( pubkey: PublicKeyBytes, url: String, - validator_store: &ValidatorStore, + validator_store: &ValidatorStore, handle: Handle, ) -> Result { if let Err(url_err) = Url::parse(&url) { @@ -144,9 +144,9 @@ fn import_single_remotekey( Ok(ImportRemotekeyStatus::Imported) } -pub fn delete( +pub fn delete( request: DeleteRemotekeysRequest, - validator_store: Arc>, + validator_store: Arc>, task_executor: TaskExecutor, log: Logger, ) -> Result { diff --git a/validator_client/http_api/src/test_utils.rs b/validator_client/http_api/src/test_utils.rs index 3f1c5193066..e11a4e5f884 100644 --- a/validator_client/http_api/src/test_utils.rs +++ b/validator_client/http_api/src/test_utils.rs @@ -5,7 +5,6 @@ use account_utils::{ eth2_wallet::WalletBuilder, mnemonic_from_phrase, random_mnemonic, random_password, }; use deposit_contract::decode_eth1_tx_data; -use doppelganger_service::DoppelgangerService; use eth2::{ lighthouse_vc::{http_client::ValidatorClientHttpClient, types::*}, types::ErrorMessage as ApiErrorMessage, @@ -20,13 +19,14 @@ use sensitive_url::SensitiveUrl; use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME}; use slot_clock::{SlotClock, TestingSlotClock}; use std::future::Future; -use std::marker::PhantomData; use std::net::{IpAddr, Ipv4Addr}; use std::sync::Arc; use std::time::Duration; use task_executor::test_utils::TestRuntime; use tempfile::{tempdir, TempDir}; use tokio::sync::oneshot; +use validator_services::block_service::BlockService; +use validator_store::doppelganger_service::DoppelgangerService; use validator_store::{Config as ValidatorStoreConfig, ValidatorStore}; use zeroize::Zeroizing; @@ -55,7 +55,7 @@ pub struct Web3SignerValidatorScenario { pub struct ApiTester { pub client: ValidatorClientHttpClient, pub initialized_validators: Arc>, - pub validator_store: Arc>, + pub validator_store: Arc>, pub url: SensitiveUrl, pub api_token: String, pub test_runtime: TestRuntime, @@ -105,7 +105,7 @@ impl ApiTester { let test_runtime = TestRuntime::default(); - let validator_store = Arc::new(ValidatorStore::<_, E>::new( + let validator_store = Arc::new(ValidatorStore::<_>::new( initialized_validators, slashing_protection, Hash256::repeat_byte(42), @@ -127,7 +127,7 @@ impl ApiTester { let context = Arc::new(Context { task_executor: test_runtime.task_executor.clone(), api_secret, - block_service: None, + block_service: None::>, validator_dir: Some(validator_dir.path().into()), secrets_dir: Some(secrets_dir.path().into()), validator_store: Some(validator_store.clone()), @@ -138,7 +138,6 @@ impl ApiTester { log, sse_logging_components: None, slot_clock, - _phantom: PhantomData, }); let ctx = context; let (shutdown_tx, shutdown_rx) = oneshot::channel(); diff --git a/validator_client/http_api/src/tests.rs b/validator_client/http_api/src/tests.rs index 027b10e2464..08fbe64a61a 100644 --- a/validator_client/http_api/src/tests.rs +++ b/validator_client/http_api/src/tests.rs @@ -3,8 +3,8 @@ mod keystores; -use doppelganger_service::DoppelgangerService; use initialized_validators::{Config as InitializedValidatorsConfig, InitializedValidators}; +use validator_store::doppelganger_service::DoppelgangerService; use crate::{ApiSecret, Config as HttpConfig, Context}; use account_utils::{ @@ -24,7 +24,6 @@ use sensitive_url::SensitiveUrl; use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME}; use slot_clock::{SlotClock, TestingSlotClock}; use std::future::Future; -use std::marker::PhantomData; use std::net::{IpAddr, Ipv4Addr}; use std::str::FromStr; use std::sync::Arc; @@ -43,7 +42,7 @@ type E = MainnetEthSpec; struct ApiTester { client: ValidatorClientHttpClient, initialized_validators: Arc>, - validator_store: Arc>, + validator_store: Arc>, url: SensitiveUrl, slot_clock: TestingSlotClock, _validator_dir: TempDir, @@ -93,7 +92,7 @@ impl ApiTester { let test_runtime = TestRuntime::default(); - let validator_store = Arc::new(ValidatorStore::<_, E>::new( + let validator_store = Arc::new(ValidatorStore::<_>::new( initialized_validators, slashing_protection, Hash256::repeat_byte(42), @@ -102,6 +101,7 @@ impl ApiTester { slot_clock.clone(), &config, test_runtime.task_executor.clone(), + E::slots_per_epoch(), log.clone(), )); @@ -111,7 +111,7 @@ impl ApiTester { let initialized_validators = validator_store.initialized_validators(); - let context = Arc::new(Context { + let context = Arc::new(Context::<_, E> { task_executor: test_runtime.task_executor.clone(), api_secret, block_service: None, @@ -133,7 +133,6 @@ impl ApiTester { sse_logging_components: None, log, slot_clock: slot_clock.clone(), - _phantom: PhantomData, }); let ctx = context.clone(); let (listening_socket, server) = diff --git a/validator_client/http_metrics/src/lib.rs b/validator_client/http_metrics/src/lib.rs index 984b752e5a5..a7d143a51ea 100644 --- a/validator_client/http_metrics/src/lib.rs +++ b/validator_client/http_metrics/src/lib.rs @@ -37,7 +37,7 @@ impl From for Error { /// Contains objects which have shared access from inside/outside of the metrics server. pub struct Shared { - pub validator_store: Option>>, + pub validator_store: Option>>, pub duties_service: Option>>, pub genesis_time: Option, } diff --git a/validator_client/signing_method/src/lib.rs b/validator_client/signing_method/src/lib.rs index f3b62c9500b..316c1d2205c 100644 --- a/validator_client/signing_method/src/lib.rs +++ b/validator_client/signing_method/src/lib.rs @@ -12,7 +12,7 @@ use std::sync::Arc; use task_executor::TaskExecutor; use types::*; use url::Url; -use web3signer::{ForkInfo, SigningRequest, SigningResponse}; +use web3signer::{ForkInfo, MessageType, SigningRequest, SigningResponse}; pub use web3signer::Web3SignerObject; @@ -152,8 +152,13 @@ impl SigningMethod { genesis_validators_root, }); - self.get_signature_from_root(signable_message, signing_root, executor, fork_info) - .await + self.get_signature_from_root::( + signable_message, + signing_root, + executor, + fork_info, + ) + .await } pub async fn get_signature_from_root>( @@ -227,11 +232,7 @@ impl SigningMethod { // Determine the Web3Signer message type. let message_type = object.message_type(); - - if matches!( - object, - Web3SignerObject::Deposit { .. } | Web3SignerObject::ValidatorRegistration(_) - ) && fork_info.is_some() + if matches!(message_type, MessageType::ValidatorRegistration) && fork_info.is_some() { return Err(Error::GenesisForkVersionRequired); } diff --git a/validator_client/src/latency.rs b/validator_client/src/latency.rs index 22f02c7c0bc..e2a80876ec7 100644 --- a/validator_client/src/latency.rs +++ b/validator_client/src/latency.rs @@ -15,7 +15,7 @@ pub const SLOT_DELAY_DENOMINATOR: u32 = 12; pub fn start_latency_service( context: RuntimeContext, slot_clock: T, - beacon_nodes: Arc>, + beacon_nodes: Arc>, ) { let log = context.log().clone(); diff --git a/validator_client/src/lib.rs b/validator_client/src/lib.rs index 3155a234201..f99b25c5965 100644 --- a/validator_client/src/lib.rs +++ b/validator_client/src/lib.rs @@ -17,7 +17,6 @@ use beacon_node_fallback::{ use account_utils::validator_definitions::ValidatorDefinitions; use clap::ArgMatches; -use doppelganger_service::DoppelgangerService; use environment::RuntimeContext; use eth2::{reqwest::ClientBuilder, BeaconNodeHttpClient, StatusCode, Timeouts}; use initialized_validators::Error::UnableToOpenVotingKeystore; @@ -29,7 +28,6 @@ use slot_clock::SlotClock; use slot_clock::SystemTimeSlotClock; use std::fs::File; use std::io::Read; -use std::marker::PhantomData; use std::net::SocketAddr; use std::path::Path; use std::sync::Arc; @@ -48,6 +46,7 @@ use validator_services::{ sync::SyncDutiesMap, sync_committee_service::SyncCommitteeService, }; +use validator_store::doppelganger_service::DoppelgangerService; use validator_store::ValidatorStore; /// The interval between attempts to contact the beacon node during startup. @@ -82,11 +81,11 @@ pub struct ProductionValidatorClient { sync_committee_service: SyncCommitteeService, doppelganger_service: Option>, preparation_service: PreparationService, - validator_store: Arc>, + validator_store: Arc>, slot_clock: SystemTimeSlotClock, http_api_listen_addr: Option, config: Config, - beacon_nodes: Arc>, + beacon_nodes: Arc>, genesis_time: u64, } @@ -384,7 +383,7 @@ impl ProductionValidatorClient { // Initialize the number of connected, avaliable beacon nodes to 0. set_gauge(&validator_metrics::AVAILABLE_BEACON_NODES_COUNT, 0); - let mut beacon_nodes: BeaconNodeFallback<_, E> = BeaconNodeFallback::new( + let mut beacon_nodes: BeaconNodeFallback<_> = BeaconNodeFallback::new( candidates, config.beacon_node_fallback, config.broadcast_topics.clone(), @@ -392,7 +391,7 @@ impl ProductionValidatorClient { log.clone(), ); - let mut proposer_nodes: BeaconNodeFallback<_, E> = BeaconNodeFallback::new( + let mut proposer_nodes: BeaconNodeFallback<_> = BeaconNodeFallback::new( proposer_candidates, config.beacon_node_fallback, config.broadcast_topics.clone(), @@ -569,7 +568,6 @@ impl ProductionValidatorClient { sse_logging_components: self.context.sse_logging_components.clone(), slot_clock: self.slot_clock.clone(), log: log.clone(), - _phantom: PhantomData, }); let exit = self.context.executor.exit(); @@ -642,13 +640,13 @@ impl ProductionValidatorClient { } async fn init_from_beacon_node( - beacon_nodes: &BeaconNodeFallback, - proposer_nodes: &BeaconNodeFallback, + beacon_nodes: &BeaconNodeFallback, + proposer_nodes: &BeaconNodeFallback, context: &RuntimeContext, ) -> Result<(u64, Hash256), String> { loop { - beacon_nodes.update_all_candidates().await; - proposer_nodes.update_all_candidates().await; + beacon_nodes.update_all_candidates::().await; + proposer_nodes.update_all_candidates::().await; let num_available = beacon_nodes.num_available().await; let num_total = beacon_nodes.num_total().await; @@ -734,7 +732,7 @@ async fn init_from_beacon_node( } async fn wait_for_genesis( - beacon_nodes: &BeaconNodeFallback, + beacon_nodes: &BeaconNodeFallback, genesis_time: u64, context: &RuntimeContext, ) -> Result<(), String> { @@ -780,8 +778,8 @@ async fn wait_for_genesis( /// Request the version from the node, looping back and trying again on failure. Exit once the node /// has been contacted. -async fn poll_whilst_waiting_for_genesis( - beacon_nodes: &BeaconNodeFallback, +async fn poll_whilst_waiting_for_genesis( + beacon_nodes: &BeaconNodeFallback, genesis_time: Duration, log: &Logger, ) -> Result<(), String> { diff --git a/validator_client/validator_services/Cargo.toml b/validator_client/validator_services/Cargo.toml index 7dcd815541e..7aed9b2b2d0 100644 --- a/validator_client/validator_services/Cargo.toml +++ b/validator_client/validator_services/Cargo.toml @@ -9,7 +9,6 @@ beacon_node_fallback = { workspace = true } validator_metrics = { workspace = true } validator_store = { workspace = true } graffiti_file = { workspace = true } -doppelganger_service = { workspace = true } environment = { workspace = true } eth2 = { workspace = true } futures = { workspace = true } diff --git a/validator_client/validator_services/src/attestation_service.rs b/validator_client/validator_services/src/attestation_service.rs index e31ad4f661b..ff27f8db01b 100644 --- a/validator_client/validator_services/src/attestation_service.rs +++ b/validator_client/validator_services/src/attestation_service.rs @@ -16,9 +16,9 @@ use validator_store::{Error as ValidatorStoreError, ValidatorStore}; #[derive(Default)] pub struct AttestationServiceBuilder { duties_service: Option>>, - validator_store: Option>>, + validator_store: Option>>, slot_clock: Option, - beacon_nodes: Option>>, + beacon_nodes: Option>>, context: Option>, } @@ -38,7 +38,7 @@ impl AttestationServiceBuilder { self } - pub fn validator_store(mut self, store: Arc>) -> Self { + pub fn validator_store(mut self, store: Arc>) -> Self { self.validator_store = Some(store); self } @@ -48,7 +48,7 @@ impl AttestationServiceBuilder { self } - pub fn beacon_nodes(mut self, beacon_nodes: Arc>) -> Self { + pub fn beacon_nodes(mut self, beacon_nodes: Arc>) -> Self { self.beacon_nodes = Some(beacon_nodes); self } @@ -84,9 +84,9 @@ impl AttestationServiceBuilder { /// Helper to minimise `Arc` usage. pub struct Inner { duties_service: Arc>, - validator_store: Arc>, + validator_store: Arc>, slot_clock: T, - beacon_nodes: Arc>, + beacon_nodes: Arc>, context: RuntimeContext, } @@ -535,7 +535,7 @@ impl AttestationService { ); if fork_name.electra_enabled() { beacon_node - .get_validator_aggregate_attestation_v2( + .get_validator_aggregate_attestation_v2::( attestation_data.slot, attestation_data.tree_hash_root(), committee_index, diff --git a/validator_client/validator_services/src/block_service.rs b/validator_client/validator_services/src/block_service.rs index 60eb0361ad3..0c21297e7f2 100644 --- a/validator_client/validator_services/src/block_service.rs +++ b/validator_client/validator_services/src/block_service.rs @@ -45,10 +45,10 @@ impl From> for BlockError { /// Builds a `BlockService`. #[derive(Default)] pub struct BlockServiceBuilder { - validator_store: Option>>, + validator_store: Option>>, slot_clock: Option>, - beacon_nodes: Option>>, - proposer_nodes: Option>>, + beacon_nodes: Option>>, + proposer_nodes: Option>>, context: Option>, graffiti: Option, graffiti_file: Option, @@ -67,7 +67,7 @@ impl BlockServiceBuilder { } } - pub fn validator_store(mut self, store: Arc>) -> Self { + pub fn validator_store(mut self, store: Arc>) -> Self { self.validator_store = Some(store); self } @@ -77,12 +77,12 @@ impl BlockServiceBuilder { self } - pub fn beacon_nodes(mut self, beacon_nodes: Arc>) -> Self { + pub fn beacon_nodes(mut self, beacon_nodes: Arc>) -> Self { self.beacon_nodes = Some(beacon_nodes); self } - pub fn proposer_nodes(mut self, proposer_nodes: Arc>) -> Self { + pub fn proposer_nodes(mut self, proposer_nodes: Arc>) -> Self { self.proposer_nodes = Some(proposer_nodes); self } @@ -127,12 +127,12 @@ impl BlockServiceBuilder { // Combines a set of non-block-proposing `beacon_nodes` and only-block-proposing // `proposer_nodes`. -pub struct ProposerFallback { - beacon_nodes: Arc>, - proposer_nodes: Option>>, +pub struct ProposerFallback { + beacon_nodes: Arc>, + proposer_nodes: Option>>, } -impl ProposerFallback { +impl ProposerFallback { // Try `func` on `self.proposer_nodes` first. If that doesn't work, try `self.beacon_nodes`. pub async fn request_proposers_first(&self, func: F) -> Result<(), Errors> where @@ -178,10 +178,10 @@ impl ProposerFallback { /// Helper to minimise `Arc` usage. pub struct Inner { - validator_store: Arc>, + validator_store: Arc>, slot_clock: Arc, - pub beacon_nodes: Arc>, - pub proposer_nodes: Option>>, + pub beacon_nodes: Arc>, + pub proposer_nodes: Option>>, context: RuntimeContext, graffiti: Option, graffiti_file: Option, @@ -326,7 +326,7 @@ impl BlockService { #[allow(clippy::too_many_arguments)] async fn sign_and_publish_block( &self, - proposer_fallback: ProposerFallback, + proposer_fallback: ProposerFallback, slot: Slot, graffiti: Option, validator_pubkey: &PublicKeyBytes, @@ -421,7 +421,7 @@ impl BlockService { let randao_reveal = match self .validator_store - .randao_reveal(validator_pubkey, slot.epoch(E::slots_per_epoch())) + .randao_reveal::(validator_pubkey, slot.epoch(E::slots_per_epoch())) .await { Ok(signature) => signature.into(), diff --git a/validator_client/validator_services/src/duties_service.rs b/validator_client/validator_services/src/duties_service.rs index 187eb4feb50..110f7306291 100644 --- a/validator_client/validator_services/src/duties_service.rs +++ b/validator_client/validator_services/src/duties_service.rs @@ -10,7 +10,6 @@ use crate::block_service::BlockServiceNotification; use crate::sync::poll_sync_committee_duties; use crate::sync::SyncDutiesMap; use beacon_node_fallback::{ApiTopic, BeaconNodeFallback}; -use doppelganger_service::DoppelgangerStatus; use environment::RuntimeContext; use eth2::types::{ AttesterData, BeaconCommitteeSubscription, DutiesResponse, ProposerData, StateId, ValidatorId, @@ -28,6 +27,7 @@ use std::time::Duration; use tokio::{sync::mpsc::Sender, time::sleep}; use types::{ChainSpec, Epoch, EthSpec, Hash256, PublicKeyBytes, SelectionProof, Slot}; use validator_metrics::{get_int_gauge, set_int_gauge, ATTESTATION_DUTY}; +use validator_store::doppelganger_service::DoppelgangerStatus; use validator_store::{Error as ValidatorStoreError, ValidatorStore}; /// Only retain `HISTORICAL_DUTIES_EPOCHS` duties prior to the current epoch. @@ -127,11 +127,11 @@ pub struct SubscriptionSlots { /// Return `Ok(None)` if the attesting validator is not an aggregator. async fn make_selection_proof( duty: &AttesterData, - validator_store: &ValidatorStore, + validator_store: &ValidatorStore, spec: &ChainSpec, ) -> Result, Error> { let selection_proof = validator_store - .produce_selection_proof(duty.pubkey, duty.slot) + .produce_selection_proof::(duty.pubkey, duty.slot) .await .map_err(Error::FailedToProduceSelectionProof)?; @@ -215,13 +215,13 @@ pub struct DutiesService { /// Map from validator index to sync committee duties. pub sync_duties: SyncDutiesMap, /// Provides the canonical list of locally-managed validators. - pub validator_store: Arc>, + pub validator_store: Arc>, /// Maps unknown validator pubkeys to the next slot time when a poll should be conducted again. pub unknown_validator_next_poll_slots: RwLock>, /// Tracks the current slot. pub slot_clock: T, /// Provides HTTP access to remote beacon nodes. - pub beacon_nodes: Arc>, + pub beacon_nodes: Arc>, /// The runtime for spawning tasks. pub context: RuntimeContext, /// The current chain spec. @@ -1097,7 +1097,7 @@ async fn fill_in_selection_proofs( // Sign selection proofs (serially). let duty_and_proof_results = stream::iter(relevant_duties.into_values().flatten()) .then(|duty| async { - let opt_selection_proof = make_selection_proof( + let opt_selection_proof = make_selection_proof::( &duty, &duties_service.validator_store, &duties_service.spec, @@ -1240,7 +1240,7 @@ async fn poll_beacon_proposers( // // See the function-level documentation for more information. let initial_block_proposers = duties_service.block_proposers(current_slot); - notify_block_production_service( + notify_block_production_service::( current_slot, &initial_block_proposers, block_service_tx, @@ -1330,7 +1330,7 @@ async fn poll_beacon_proposers( // // See the function-level documentation for more reasoning about this behaviour. if !additional_block_producers.is_empty() { - notify_block_production_service( + notify_block_production_service::( current_slot, &additional_block_producers, block_service_tx, @@ -1357,11 +1357,11 @@ async fn poll_beacon_proposers( } /// Notify the block service if it should produce a block. -async fn notify_block_production_service( +async fn notify_block_production_service( current_slot: Slot, block_proposers: &HashSet, block_service_tx: &mut Sender, - validator_store: &ValidatorStore, + validator_store: &ValidatorStore, log: &Logger, ) { let non_doppelganger_proposers = block_proposers diff --git a/validator_client/validator_services/src/preparation_service.rs b/validator_client/validator_services/src/preparation_service.rs index 480f4af2b3c..827e3355a42 100644 --- a/validator_client/validator_services/src/preparation_service.rs +++ b/validator_client/validator_services/src/preparation_service.rs @@ -1,6 +1,5 @@ use beacon_node_fallback::{ApiTopic, BeaconNodeFallback}; use bls::PublicKeyBytes; -use doppelganger_service::DoppelgangerStatus; use environment::RuntimeContext; use parking_lot::RwLock; use slog::{debug, error, info, warn}; @@ -15,6 +14,7 @@ use types::{ Address, ChainSpec, EthSpec, ProposerPreparationData, SignedValidatorRegistrationData, ValidatorRegistrationData, }; +use validator_store::doppelganger_service::DoppelgangerStatus; use validator_store::{Error as ValidatorStoreError, ProposalData, ValidatorStore}; /// Number of epochs before the Bellatrix hard fork to begin posting proposer preparations. @@ -26,9 +26,9 @@ const EPOCHS_PER_VALIDATOR_REGISTRATION_SUBMISSION: u64 = 1; /// Builds an `PreparationService`. #[derive(Default)] pub struct PreparationServiceBuilder { - validator_store: Option>>, + validator_store: Option>>, slot_clock: Option, - beacon_nodes: Option>>, + beacon_nodes: Option>>, context: Option>, builder_registration_timestamp_override: Option, validator_registration_batch_size: Option, @@ -46,7 +46,7 @@ impl PreparationServiceBuilder { } } - pub fn validator_store(mut self, store: Arc>) -> Self { + pub fn validator_store(mut self, store: Arc>) -> Self { self.validator_store = Some(store); self } @@ -56,7 +56,7 @@ impl PreparationServiceBuilder { self } - pub fn beacon_nodes(mut self, beacon_nodes: Arc>) -> Self { + pub fn beacon_nodes(mut self, beacon_nodes: Arc>) -> Self { self.beacon_nodes = Some(beacon_nodes); self } @@ -110,9 +110,9 @@ impl PreparationServiceBuilder { /// Helper to minimise `Arc` usage. pub struct Inner { - validator_store: Arc>, + validator_store: Arc>, slot_clock: T, - beacon_nodes: Arc>, + beacon_nodes: Arc>, context: RuntimeContext, builder_registration_timestamp_override: Option, // Used to track unpublished validator registration changes. @@ -430,7 +430,7 @@ impl PreparationService { let signed_data = match self .validator_store - .sign_validator_registration_data(ValidatorRegistrationData { + .sign_validator_registration_data::(ValidatorRegistrationData { fee_recipient, gas_limit, timestamp, diff --git a/validator_client/validator_services/src/sync.rs b/validator_client/validator_services/src/sync.rs index af501326f42..c693b53a03f 100644 --- a/validator_client/validator_services/src/sync.rs +++ b/validator_client/validator_services/src/sync.rs @@ -1,5 +1,4 @@ use crate::duties_service::{DutiesService, Error}; -use doppelganger_service::DoppelgangerStatus; use futures::future::join_all; use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; use slog::{crit, debug, info, warn}; @@ -8,6 +7,7 @@ use std::collections::{HashMap, HashSet}; use std::marker::PhantomData; use std::sync::Arc; use types::{ChainSpec, EthSpec, PublicKeyBytes, Slot, SyncDuty, SyncSelectionProof, SyncSubnetId}; +use validator_store::doppelganger_service::DoppelgangerStatus; use validator_store::Error as ValidatorStoreError; /// Number of epochs in advance to compute selection proofs when not in `distributed` mode. @@ -548,7 +548,7 @@ pub async fn fill_in_aggregation_proofs( let proof = match duties_service_ref .validator_store - .produce_sync_selection_proof(&duty.pubkey, proof_slot, *subnet_id) + .produce_sync_selection_proof::(&duty.pubkey, proof_slot, *subnet_id) .await { Ok(proof) => proof, diff --git a/validator_client/validator_services/src/sync_committee_service.rs b/validator_client/validator_services/src/sync_committee_service.rs index 3ab5b33b6cc..de228b0dbb1 100644 --- a/validator_client/validator_services/src/sync_committee_service.rs +++ b/validator_client/validator_services/src/sync_committee_service.rs @@ -41,9 +41,9 @@ impl Deref for SyncCommitteeService { pub struct Inner { duties_service: Arc>, - validator_store: Arc>, + validator_store: Arc>, slot_clock: T, - beacon_nodes: Arc>, + beacon_nodes: Arc>, context: RuntimeContext, /// Boolean to track whether the service has posted subscriptions to the BN at least once. /// @@ -54,9 +54,9 @@ pub struct Inner { impl SyncCommitteeService { pub fn new( duties_service: Arc>, - validator_store: Arc>, + validator_store: Arc>, slot_clock: T, - beacon_nodes: Arc>, + beacon_nodes: Arc>, context: RuntimeContext, ) -> Self { Self { @@ -252,7 +252,7 @@ impl SyncCommitteeService { let signature_futures = validator_duties.iter().map(|duty| async move { match self .validator_store - .produce_sync_committee_signature( + .produce_sync_committee_signature::( slot, beacon_block_root, duty.validator_index, diff --git a/validator_client/validator_store/Cargo.toml b/validator_client/validator_store/Cargo.toml index 99c3025a30d..b7679d86c5e 100644 --- a/validator_client/validator_store/Cargo.toml +++ b/validator_client/validator_store/Cargo.toml @@ -10,7 +10,9 @@ path = "src/lib.rs" [dependencies] account_utils = { workspace = true } -doppelganger_service = { workspace = true } +beacon_node_fallback = { workspace = true } +environment = { workspace = true } +eth2 = { workspace = true } initialized_validators = { workspace = true } parking_lot = { workspace = true } serde = { workspace = true } @@ -20,4 +22,9 @@ slog = { workspace = true } slot_clock = { workspace = true } task_executor = { workspace = true } types = { workspace = true } +tokio = { workspace = true } validator_metrics = { workspace = true } + +[dev-dependencies] +futures = { workspace = true } +logging = {workspace = true } diff --git a/validator_client/doppelganger_service/src/lib.rs b/validator_client/validator_store/src/doppelganger_service.rs similarity index 98% rename from validator_client/doppelganger_service/src/lib.rs rename to validator_client/validator_store/src/doppelganger_service.rs index 5abb6dbbbff..32e4194783b 100644 --- a/validator_client/doppelganger_service/src/lib.rs +++ b/validator_client/validator_store/src/doppelganger_service.rs @@ -42,6 +42,8 @@ use task_executor::ShutdownReason; use tokio::time::sleep; use types::{Epoch, EthSpec, PublicKeyBytes, Slot}; +use crate::ValidatorStore; + /// A wrapper around `PublicKeyBytes` which encodes information about the status of a validator /// pubkey with regards to doppelganger protection. #[derive(Debug, PartialEq)] @@ -113,13 +115,6 @@ struct LivenessResponses { /// validators on the network. pub const DEFAULT_REMAINING_DETECTION_EPOCHS: u64 = 1; -/// This crate cannot depend on ValidatorStore as validator_store depends on this crate and -/// initialises the doppelganger protection. For this reason, we abstract the validator store -/// functions this service needs through the following trait -pub trait DoppelgangerValidatorStore { - fn get_validator_index(&self, pubkey: &PublicKeyBytes) -> Option; -} - /// Store the per-validator status of doppelganger checking. #[derive(Debug, PartialEq)] pub struct DoppelgangerState { @@ -162,8 +157,8 @@ impl DoppelgangerState { /// If the BN fails to respond to either of these requests, simply return an empty response. /// This behaviour is to help prevent spurious failures on the BN from needlessly preventing /// doppelganger progression. -async fn beacon_node_liveness<'a, T: 'static + SlotClock, E: EthSpec>( - beacon_nodes: Arc>, +async fn beacon_node_liveness<'a, T: 'static + SlotClock>( + beacon_nodes: Arc>, log: Logger, current_epoch: Epoch, validator_indices: Vec, @@ -286,17 +281,16 @@ impl DoppelgangerService { /// Starts a reoccurring future which will try to keep the doppelganger service updated each /// slot. - pub fn start_update_service( + pub fn start_update_service( service: Arc, context: RuntimeContext, - validator_store: Arc, - beacon_nodes: Arc>, + validator_store: Arc>, + beacon_nodes: Arc>, slot_clock: T, ) -> Result<(), String> where E: EthSpec, T: 'static + SlotClock, - V: DoppelgangerValidatorStore + Send + Sync + 'static, { // Define the `get_index` function as one that uses the validator store. let get_index = move |pubkey| validator_store.get_validator_index(&pubkey); @@ -806,7 +800,7 @@ mod test { .expect("index should exist"); self.doppelganger - .register_new_validator::(pubkey, &self.slot_clock) + .register_new_validator(pubkey, &self.slot_clock, E::slots_per_epoch()) .unwrap(); self.doppelganger .doppelganger_states diff --git a/validator_client/validator_store/src/lib.rs b/validator_client/validator_store/src/lib.rs index a74ed6ba21f..e5c1dbae0ca 100644 --- a/validator_client/validator_store/src/lib.rs +++ b/validator_client/validator_store/src/lib.rs @@ -1,5 +1,5 @@ use account_utils::validator_definitions::{PasswordStorage, ValidatorDefinition}; -use doppelganger_service::{DoppelgangerService, DoppelgangerStatus, DoppelgangerValidatorStore}; +use doppelganger_service::{DoppelgangerService, DoppelgangerStatus}; use initialized_validators::InitializedValidators; use parking_lot::{Mutex, RwLock}; use serde::{Deserialize, Serialize}; @@ -9,7 +9,6 @@ use slashing_protection::{ }; use slog::{crit, error, info, warn, Logger}; use slot_clock::SlotClock; -use std::marker::PhantomData; use std::path::Path; use std::sync::Arc; use task_executor::TaskExecutor; @@ -23,6 +22,8 @@ use types::{ ValidatorRegistrationData, VoluntaryExit, }; +pub mod doppelganger_service; + #[derive(Debug, PartialEq)] pub enum Error { DoppelgangerProtected(PublicKeyBytes), @@ -76,7 +77,7 @@ const SLASHING_PROTECTION_HISTORY_EPOCHS: u64 = 512; /// https://github.com/ethereum/builder-specs/issues/17 pub const DEFAULT_GAS_LIMIT: u64 = 30_000_000; -pub struct ValidatorStore { +pub struct ValidatorStore { validators: Arc>, slashing_protection: SlashingDatabase, slashing_protection_last_prune: Arc>, @@ -93,16 +94,15 @@ pub struct ValidatorStore { builder_boost_factor: Option, task_executor: TaskExecutor, slots_per_epoch: u64, - _phantom: PhantomData, } -impl DoppelgangerValidatorStore for ValidatorStore { +impl ValidatorStore { fn get_validator_index(&self, pubkey: &PublicKeyBytes) -> Option { self.validator_index(pubkey) } } -impl ValidatorStore { +impl ValidatorStore { // All arguments are different types. Making the fields `pub` is undesired. A builder seems // unnecessary. #[allow(clippy::too_many_arguments)] @@ -135,7 +135,6 @@ impl ValidatorStore { builder_boost_factor: config.builder_boost_factor, task_executor, slots_per_epoch, - _phantom: PhantomData, } } @@ -417,7 +416,7 @@ impl ValidatorStore { } } - pub async fn randao_reveal( + pub async fn randao_reveal( &self, validator_pubkey: PublicKeyBytes, signing_epoch: Epoch, @@ -582,7 +581,7 @@ impl ValidatorStore { }) } - pub async fn sign_block>( + pub async fn sign_block>( &self, validator_pubkey: PublicKeyBytes, block: BeaconBlock, @@ -630,7 +629,7 @@ impl ValidatorStore { ); let signature = signing_method - .get_signature::( + .get_signature( SignableMessage::BeaconBlock(&block), signing_context, &self.spec, @@ -678,7 +677,7 @@ impl ValidatorStore { } } - pub async fn sign_attestation( + pub async fn sign_attestation( &self, validator_pubkey: PublicKeyBytes, validator_committee_position: usize, @@ -774,7 +773,7 @@ impl ValidatorStore { } } - pub async fn sign_voluntary_exit( + pub async fn sign_voluntary_exit( &self, validator_pubkey: PublicKeyBytes, voluntary_exit: VoluntaryExit, @@ -803,7 +802,7 @@ impl ValidatorStore { }) } - pub async fn sign_validator_registration_data( + pub async fn sign_validator_registration_data( &self, validator_registration_data: ValidatorRegistrationData, ) -> Result { @@ -836,7 +835,7 @@ impl ValidatorStore { /// /// The resulting `SignedAggregateAndProof` is sent on the aggregation channel and cannot be /// modified by actors other than the signing validator. - pub async fn produce_signed_aggregate_and_proof( + pub async fn produce_signed_aggregate_and_proof( &self, validator_pubkey: PublicKeyBytes, aggregator_index: u64, @@ -871,7 +870,7 @@ impl ValidatorStore { /// Produces a `SelectionProof` for the `slot`, signed by with corresponding secret key to /// `validator_pubkey`. - pub async fn produce_selection_proof( + pub async fn produce_selection_proof( &self, validator_pubkey: PublicKeyBytes, slot: Slot, @@ -907,7 +906,7 @@ impl ValidatorStore { } /// Produce a `SyncSelectionProof` for `slot` signed by the secret key of `validator_pubkey`. - pub async fn produce_sync_selection_proof( + pub async fn produce_sync_selection_proof( &self, validator_pubkey: &PublicKeyBytes, slot: Slot, @@ -943,7 +942,7 @@ impl ValidatorStore { Ok(signature.into()) } - pub async fn produce_sync_committee_signature( + pub async fn produce_sync_committee_signature( &self, slot: Slot, beacon_block_root: Hash256, @@ -982,7 +981,7 @@ impl ValidatorStore { }) } - pub async fn produce_signed_contribution_and_proof( + pub async fn produce_signed_contribution_and_proof( &self, aggregator_index: u64, aggregator_pubkey: PublicKeyBytes,