diff --git a/beacon_node/beacon_chain/src/validator_monitor.rs b/beacon_node/beacon_chain/src/validator_monitor.rs index 015efe0c64e..b0395c43bea 100644 --- a/beacon_node/beacon_chain/src/validator_monitor.rs +++ b/beacon_node/beacon_chain/src/validator_monitor.rs @@ -440,6 +440,16 @@ impl ValidatorMonitor { .and_then(|pubkey| self.validators.get(pubkey)) } + /// Return `true` if the `validator_index` has been registered with `self`. + pub fn contains_validator(&self, validator_index: u64) -> bool { + self.indices.contains_key(&validator_index) + } + + /// Return `true` if the automatic validator registration is enabled. + pub fn auto_register_enabled(&self) -> bool { + self.auto_register + } + /// Returns the number of validators monitored by `self`. pub fn num_validators(&self) -> usize { self.validators.len() diff --git a/beacon_node/http_api/src/lib.rs b/beacon_node/http_api/src/lib.rs index d6b80510764..3847f019c03 100644 --- a/beacon_node/http_api/src/lib.rs +++ b/beacon_node/http_api/src/lib.rs @@ -1877,10 +1877,26 @@ pub fn serve( chain: Arc>| { blocking_json_task(move || { for subscription in &subscriptions { - chain - .validator_monitor - .write() - .auto_register_local_validator(subscription.validator_index); + // Assign the result from the read to a separate variable, to avoid a Rust + // quirk where a read-lock obtained inside an `if` statement is for the + // execution inside it. + // + // Checking the read-lock first helps avoid lengthy waits for the + // write-lock. Although another thread may add the validator between + // dropping the read-lock and obtaining the write-lock, there's no harm in + // registering the same validator twice. + let should_register = { + let validator_monitor = chain.validator_monitor.read(); + validator_monitor.auto_register_enabled() + && validator_monitor + .contains_validator(subscription.validator_index) + }; + if should_register { + chain + .validator_monitor + .write() + .auto_register_local_validator(subscription.validator_index); + } let subscription = api_types::ValidatorSubscription { validator_index: subscription.validator_index,