mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-17 21:08:32 +00:00
Implement slasher (#1567)
This is an implementation of a slasher that lives inside the BN and can be enabled via `lighthouse bn --slasher`. Features included in this PR: - [x] Detection of attester slashing conditions (double votes, surrounds existing, surrounded by existing) - [x] Integration into Lighthouse's attestation verification flow - [x] Detection of proposer slashing conditions - [x] Extraction of attestations from blocks as they are verified - [x] Compression of chunks - [x] Configurable history length - [x] Pruning of old attestations and blocks - [x] More tests Future work: * Focus on a slice of history separate from the most recent N epochs (e.g. epochs `current - K` to `current - M`) * Run out-of-process * Ingest attestations from the chain without a resync Design notes are here https://hackmd.io/@sproul/HJSEklmPL
This commit is contained in:
@@ -11,7 +11,9 @@ use tree_hash_derive::TreeHash;
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||
)]
|
||||
pub struct BeaconBlockHeader {
|
||||
pub slot: Slot,
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
|
||||
@@ -10,7 +10,9 @@ use tree_hash_derive::TreeHash;
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||
)]
|
||||
pub struct ProposerSlashing {
|
||||
pub signed_header_1: SignedBeaconBlockHeader,
|
||||
pub signed_header_2: SignedBeaconBlockHeader,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
test_utils::TestRandom, BeaconBlock, ChainSpec, Domain, EthSpec, Fork, Hash256, PublicKey,
|
||||
SignedRoot, SigningData, Slot,
|
||||
SignedBeaconBlockHeader, SignedRoot, SigningData, Slot,
|
||||
};
|
||||
use bls::Signature;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@@ -82,6 +82,14 @@ impl<E: EthSpec> SignedBeaconBlock<E> {
|
||||
self.signature.verify(pubkey, message)
|
||||
}
|
||||
|
||||
/// Produce a signed beacon block header corresponding to this block.
|
||||
pub fn signed_block_header(&self) -> SignedBeaconBlockHeader {
|
||||
SignedBeaconBlockHeader {
|
||||
message: self.message.block_header(),
|
||||
signature: self.signature.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience accessor for the block's slot.
|
||||
pub fn slot(&self) -> Slot {
|
||||
self.message.slot
|
||||
|
||||
@@ -1,21 +1,60 @@
|
||||
use crate::{test_utils::TestRandom, BeaconBlockHeader};
|
||||
use bls::Signature;
|
||||
|
||||
use crate::{
|
||||
test_utils::TestRandom, BeaconBlockHeader, ChainSpec, Domain, EthSpec, Fork, Hash256,
|
||||
PublicKey, Signature, SignedRoot,
|
||||
};
|
||||
use derivative::Derivative;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz::Encode;
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
/// An exit voluntarily submitted a validator who wishes to withdraw.
|
||||
/// A signed header of a `BeaconBlock`.
|
||||
///
|
||||
/// Spec v0.12.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
#[derive(Derivative, Debug, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
#[derivative(PartialEq, Eq)]
|
||||
pub struct SignedBeaconBlockHeader {
|
||||
pub message: BeaconBlockHeader,
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
/// Implementation of non-crypto-secure `Hash`, for use with `HashMap` and `HashSet`.
|
||||
///
|
||||
/// Guarantees `header1 == header2 -> hash(header1) == hash(header2)`.
|
||||
///
|
||||
/// Used in the slasher.
|
||||
impl Hash for SignedBeaconBlockHeader {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.message.hash(state);
|
||||
self.signature.as_ssz_bytes().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl SignedBeaconBlockHeader {
|
||||
/// Verify that this block header was signed by `pubkey`.
|
||||
pub fn verify_signature<E: EthSpec>(
|
||||
&self,
|
||||
pubkey: &PublicKey,
|
||||
fork: &Fork,
|
||||
genesis_validators_root: Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> bool {
|
||||
let domain = spec.get_domain(
|
||||
self.message.slot.epoch(E::slots_per_epoch()),
|
||||
Domain::BeaconProposer,
|
||||
fork,
|
||||
genesis_validators_root,
|
||||
);
|
||||
|
||||
let message = self.message.signing_root(domain);
|
||||
|
||||
self.signature.verify(pubkey, message)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user