Implement Slashing Protection (#1116)

* Implement slashing protection

Roll-up of #588 with some conflicts resolved

* WIP improvements

* Require slot uniqueness for blocks (rather than epochs)
* Native DB support for Slot and Epoch
* Simplify surrounding/surrounded-by queries

* Implement unified slashing protection database

A single SQL database saves on open file descriptors.

* Make slashing protection concurrency safe.

Revive tests, add parallel tests.

* Some simplifications

* Auto-registration, test clean-ups

* More tests, clean-ups, hardening

* Fix comments in BLS

* Optimise bulk validator registration

* Delete outdated tests

* Use bundled SQLite in slashing protection

* Auto-register validators in simulation

* Use real signing_root in slashing protection

* Update book for --auto-register

* Refine log messages and help flags

* Correct typo in Cargo.toml authors

* Fix merge conflicts

* Safer error handling in sqlite slot/epoch

* Address review comments

* Add attestation test mutating block root

Co-authored-by: pscott <scottpiriou@gmail.com>
This commit is contained in:
Michael Sproul
2020-05-18 16:25:16 +10:00
committed by GitHub
parent 90b3953dda
commit 2d8e2dd7f5
30 changed files with 1720 additions and 52 deletions

View File

@@ -35,7 +35,7 @@ fn dir_name(voting_pubkey: &PublicKey) -> String {
/// Represents the files/objects for each dedicated lighthouse validator directory.
///
/// Generally lives in `~/.lighthouse/validators/`.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub struct ValidatorDirectory {
pub directory: PathBuf,
pub voting_keypair: Option<Keypair>,
@@ -147,11 +147,13 @@ pub struct ValidatorDirectoryBuilder {
}
impl ValidatorDirectoryBuilder {
/// Set the specification for this validator.
pub fn spec(mut self, spec: ChainSpec) -> Self {
self.spec = Some(spec);
self
}
/// Use the `MAX_EFFECTIVE_BALANCE` as this validator's deposit.
pub fn full_deposit_amount(mut self) -> Result<Self, String> {
let spec = self
.spec
@@ -161,17 +163,24 @@ impl ValidatorDirectoryBuilder {
Ok(self)
}
/// Use a validator deposit of `gwei`.
pub fn custom_deposit_amount(mut self, gwei: u64) -> Self {
self.amount = Some(gwei);
self
}
/// Generate keypairs using `Keypair::random()`.
pub fn thread_random_keypairs(mut self) -> Self {
self.voting_keypair = Some(Keypair::random());
self.withdrawal_keypair = Some(Keypair::random());
self
}
/// Generate insecure, deterministic keypairs.
///
///
/// ## Warning
/// Only for use in testing. Do not store value in these keys.
pub fn insecure_keypairs(mut self, index: usize) -> Self {
let keypair = generate_deterministic_keypair(index);
self.voting_keypair = Some(keypair.clone());
@@ -203,6 +212,7 @@ impl ValidatorDirectoryBuilder {
Ok(self)
}
/// Write the validators keypairs to disk.
pub fn write_keypair_files(self) -> Result<Self, String> {
let voting_keypair = self
.voting_keypair
@@ -285,7 +295,7 @@ impl ValidatorDirectoryBuilder {
.directory
.as_ref()
.map(|directory| directory.join(ETH1_DEPOSIT_DATA_FILE))
.ok_or_else(|| "write_eth1_data_filer requires a directory")?;
.ok_or_else(|| "write_eth1_data_file requires a directory")?;
let (deposit_data, _) = self.get_deposit_data()?;
@@ -328,8 +338,10 @@ impl ValidatorDirectoryBuilder {
}
pub fn build(self) -> Result<ValidatorDirectory, String> {
let directory = self.directory.ok_or_else(|| "build requires a directory")?;
Ok(ValidatorDirectory {
directory: self.directory.ok_or_else(|| "build requires a directory")?,
directory,
voting_keypair: self.voting_keypair,
withdrawal_keypair: self.withdrawal_keypair,
deposit_data: self.deposit_data,