mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-19 22:08:30 +00:00
Process exits and slashings off the network (#1253)
* Process exits and slashings off the network * Fix rest_api tests * Add op verification tests * Add tests for pruning of slashings in the op pool * Address Paul's review comments
This commit is contained in:
@@ -46,7 +46,7 @@ pub use typenum;
|
||||
/// // Push a value to if it _does_ exceed the maximum.
|
||||
/// assert!(long.push(6).is_err());
|
||||
/// ```
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct VariableList<T, N> {
|
||||
vec: Vec<T>,
|
||||
|
||||
@@ -9,6 +9,7 @@ pub mod per_block_processing;
|
||||
pub mod per_epoch_processing;
|
||||
pub mod per_slot_processing;
|
||||
pub mod test_utils;
|
||||
pub mod verify_operation;
|
||||
|
||||
pub use genesis::{
|
||||
eth2_genesis_time, initialize_beacon_state_from_eth1, is_valid_genesis_state,
|
||||
@@ -20,3 +21,4 @@ pub use per_block_processing::{
|
||||
};
|
||||
pub use per_epoch_processing::{errors::EpochProcessingError, per_epoch_processing};
|
||||
pub use per_slot_processing::{per_slot_processing, Error as SlotProcessingError};
|
||||
pub use verify_operation::{SigVerifiedOp, VerifyOperation};
|
||||
|
||||
73
consensus/state_processing/src/verify_operation.rs
Normal file
73
consensus/state_processing/src/verify_operation.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use crate::per_block_processing::{
|
||||
errors::{
|
||||
AttesterSlashingValidationError, ExitValidationError, ProposerSlashingValidationError,
|
||||
},
|
||||
verify_attester_slashing, verify_exit, verify_proposer_slashing,
|
||||
};
|
||||
use crate::VerifySignatures;
|
||||
use types::{
|
||||
AttesterSlashing, BeaconState, ChainSpec, EthSpec, ProposerSlashing, SignedVoluntaryExit,
|
||||
};
|
||||
|
||||
/// Wrapper around an operation type that acts as proof that its signature has been checked.
|
||||
///
|
||||
/// The inner field is private, meaning instances of this type can only be constructed
|
||||
/// by calling `validate`.
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct SigVerifiedOp<T>(T);
|
||||
|
||||
impl<T> SigVerifiedOp<T> {
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for operations that can be verified and transformed into a `SigVerifiedOp`.
|
||||
pub trait VerifyOperation<E: EthSpec>: Sized {
|
||||
type Error;
|
||||
|
||||
fn validate(
|
||||
self,
|
||||
state: &BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<SigVerifiedOp<Self>, Self::Error>;
|
||||
}
|
||||
|
||||
impl<E: EthSpec> VerifyOperation<E> for SignedVoluntaryExit {
|
||||
type Error = ExitValidationError;
|
||||
|
||||
fn validate(
|
||||
self,
|
||||
state: &BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<SigVerifiedOp<Self>, Self::Error> {
|
||||
verify_exit(state, &self, VerifySignatures::True, spec)?;
|
||||
Ok(SigVerifiedOp(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> VerifyOperation<E> for AttesterSlashing<E> {
|
||||
type Error = AttesterSlashingValidationError;
|
||||
|
||||
fn validate(
|
||||
self,
|
||||
state: &BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<SigVerifiedOp<Self>, Self::Error> {
|
||||
verify_attester_slashing(state, &self, VerifySignatures::True, spec)?;
|
||||
Ok(SigVerifiedOp(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: EthSpec> VerifyOperation<E> for ProposerSlashing {
|
||||
type Error = ProposerSlashingValidationError;
|
||||
|
||||
fn validate(
|
||||
self,
|
||||
state: &BeaconState<E>,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<SigVerifiedOp<Self>, Self::Error> {
|
||||
verify_proposer_slashing(&self, state, VerifySignatures::True, spec)?;
|
||||
Ok(SigVerifiedOp(self))
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ rand_xorshift = "0.2.0"
|
||||
cached_tree_hash = { path = "../cached_tree_hash" }
|
||||
serde_yaml = "0.8.11"
|
||||
tempfile = "3.1.0"
|
||||
derivative = "2.1.1"
|
||||
rusqlite = { version = "0.23.1", features = ["bundled"], optional = true }
|
||||
arbitrary = { version = "0.4.4", features = ["derive"], optional = true }
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::{test_utils::TestRandom, EthSpec, IndexedAttestation};
|
||||
|
||||
use derivative::Derivative;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
@@ -9,7 +10,20 @@ use tree_hash_derive::TreeHash;
|
||||
///
|
||||
/// Spec v0.11.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
#[derive(
|
||||
Derivative,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Encode,
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
#[derivative(Hash(bound = "T: EthSpec"))]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct AttesterSlashing<T: EthSpec> {
|
||||
pub attestation_1: IndexedAttestation<T>,
|
||||
|
||||
@@ -8,7 +8,7 @@ use ssz_types::typenum::{
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq {
|
||||
pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq + Eq {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq {
|
||||
/*
|
||||
* Misc
|
||||
*/
|
||||
type MaxValidatorsPerCommittee: Unsigned + Clone + Sync + Send + Debug + PartialEq;
|
||||
type MaxValidatorsPerCommittee: Unsigned + Clone + Sync + Send + Debug + PartialEq + Eq;
|
||||
/*
|
||||
* Time parameters
|
||||
*/
|
||||
@@ -135,7 +135,7 @@ macro_rules! params_from_eth_spec {
|
||||
///
|
||||
/// Spec v0.11.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct MainnetEthSpec;
|
||||
|
||||
impl EthSpec for MainnetEthSpec {
|
||||
@@ -173,7 +173,7 @@ pub type FoundationBeaconState = BeaconState<MainnetEthSpec>;
|
||||
///
|
||||
/// Spec v0.11.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct MinimalEthSpec;
|
||||
|
||||
impl EthSpec for MinimalEthSpec {
|
||||
@@ -212,7 +212,7 @@ pub type MinimalBeaconState = BeaconState<MinimalEthSpec>;
|
||||
|
||||
/// Interop testnet spec
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct InteropEthSpec;
|
||||
|
||||
impl EthSpec for InteropEthSpec {
|
||||
|
||||
@@ -12,7 +12,17 @@ use tree_hash_derive::TreeHash;
|
||||
/// Spec v0.11.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(
|
||||
Debug, Clone, PartialEq, Default, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Default,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Encode,
|
||||
Decode,
|
||||
TreeHash,
|
||||
TestRandom,
|
||||
)]
|
||||
pub struct Fork {
|
||||
#[serde(
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::{test_utils::TestRandom, AggregateSignature, AttestationData, EthSpec, VariableList};
|
||||
|
||||
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;
|
||||
|
||||
@@ -11,7 +12,9 @@ use tree_hash_derive::TreeHash;
|
||||
///
|
||||
/// Spec v0.11.1
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom,
|
||||
)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct IndexedAttestation<T: EthSpec> {
|
||||
/// Lists validator registry indices, not committee indices.
|
||||
@@ -37,6 +40,19 @@ impl<T: EthSpec> IndexedAttestation<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of non-crypto-secure `Hash`, for use with `HashMap` and `HashSet`.
|
||||
///
|
||||
/// Guarantees `att1 == att2 -> hash(att1) == hash(att2)`.
|
||||
///
|
||||
/// Used in the operation pool.
|
||||
impl<T: EthSpec> Hash for IndexedAttestation<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.attesting_indices.hash(state);
|
||||
self.data.hash(state);
|
||||
self.signature.as_ssz_bytes().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -93,6 +93,7 @@ pub use crate::voluntary_exit::VoluntaryExit;
|
||||
pub type CommitteeIndex = u64;
|
||||
pub type Hash256 = H256;
|
||||
pub type Address = H160;
|
||||
pub type ForkVersion = [u8; 4];
|
||||
|
||||
pub use bls::{
|
||||
AggregatePublicKey, AggregateSignature, Keypair, PublicKey, PublicKeyBytes, SecretKey,
|
||||
|
||||
@@ -13,10 +13,6 @@ impl TestingAttesterSlashingBuilder {
|
||||
///
|
||||
/// - `validator_index: u64`
|
||||
/// - `message: &[u8]`
|
||||
/// - `epoch: Epoch`
|
||||
/// - `domain: Domain`
|
||||
///
|
||||
/// Where domain is a domain "constant" (e.g., `spec.domain_attestation`).
|
||||
pub fn double_vote<F, T: EthSpec>(
|
||||
test_task: AttesterSlashingTestTask,
|
||||
validator_indices: &[u64],
|
||||
|
||||
Reference in New Issue
Block a user