Doppelganger detection (#2230)

## Issue Addressed

Resolves #2069 

## Proposed Changes

- Adds a `--doppelganger-detection` flag
- Adds a `lighthouse/seen_validators` endpoint, which will make it so the lighthouse VC is not interopable with other client beacon nodes if the `--doppelganger-detection` flag is used, but hopefully this will become standardized. Relevant Eth2 API repo issue: https://github.com/ethereum/eth2.0-APIs/issues/64
- If the `--doppelganger-detection` flag is used, the VC will wait until the beacon node is synced, and then wait an additional 2 epochs. The reason for this is to make sure the beacon node is able to subscribe to the subnets our validators should be attesting on. I think an alternative would be to have the beacon node subscribe to all subnets for 2+ epochs on startup by default.

## Additional Info

I'd like to add tests and would appreciate feedback. 

TODO:  handle validators started via the API, potentially make this default behavior

Co-authored-by: realbigsean <seananderson33@gmail.com>
Co-authored-by: Michael Sproul <michael@sigmaprime.io>
Co-authored-by: Paul Hauner <paul@paulhauner.com>
This commit is contained in:
realbigsean
2021-07-31 03:50:52 +00:00
parent 834ee98bc2
commit c5786a8821
38 changed files with 2302 additions and 201 deletions

View File

@@ -83,6 +83,7 @@ impl fmt::Display for Error {
pub struct Timeouts {
pub attestation: Duration,
pub attester_duties: Duration,
pub liveness: Duration,
pub proposal: Duration,
pub proposer_duties: Duration,
}
@@ -92,6 +93,7 @@ impl Timeouts {
Timeouts {
attestation: timeout,
attester_duties: timeout,
liveness: timeout,
proposal: timeout,
proposer_duties: timeout,
}
@@ -1103,6 +1105,30 @@ impl BeaconNodeHttpClient {
.await
}
/// `POST lighthouse/liveness`
pub async fn post_lighthouse_liveness(
&self,
ids: &[u64],
epoch: Epoch,
) -> Result<GenericResponse<Vec<LivenessResponseData>>, Error> {
let mut path = self.server.full.clone();
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("lighthouse")
.push("liveness");
self.post_with_timeout_and_response(
path,
&LivenessRequestData {
indices: ids.to_vec(),
epoch,
},
self.timeouts.liveness,
)
.await
}
/// `POST validator/duties/attester/{epoch}`
pub async fn post_validator_duties_attester(
&self,

View File

@@ -847,6 +847,21 @@ impl FromStr for Accept {
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct LivenessRequestData {
pub epoch: Epoch,
#[serde(with = "serde_utils::quoted_u64_vec")]
pub indices: Vec<u64>,
}
#[derive(PartialEq, Debug, Serialize, Deserialize)]
pub struct LivenessResponseData {
#[serde(with = "serde_utils::quoted_u64")]
pub index: u64,
pub epoch: Epoch,
pub is_live: bool,
}
#[cfg(test)]
mod tests {
use super::*;