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:
Michael Sproul
2020-06-18 21:06:34 +10:00
committed by GitHub
parent 3199b1a6f2
commit bcb6afa0aa
27 changed files with 956 additions and 273 deletions

View File

@@ -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>,

View File

@@ -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};

View 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))
}
}

View File

@@ -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 }

View File

@@ -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>,

View File

@@ -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 {

View File

@@ -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(

View File

@@ -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::*;

View File

@@ -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,

View File

@@ -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],