mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-10 12:11:59 +00:00
Update VC and BN APIs for naive aggregation (#950)
* Refactor `Attestation` production * Add constant * Start refactor for aggregation * Return early when no attesting validators * Refactor into individual functions * Tidy, add comments * Add first draft of NaiveAggregationPool * Further progress on naive aggregation pool * Fix compile errors in VC * Change locking logic for naive pool * Introduce AttesationType * Add pruning, comments * Add MAX_ATTESTATIONS_PER_SLOT restriction * Add pruning based on slot * Update BN for new aggregation fns * Fix test compile errors * Fix failing rest_api test * Move SignedAggregateAndProof into own file * Update docs, fix warning * Tidy some formatting in validator API * Remove T::default_spec from signing * Fix failing rest test * Tidy * Add test, fix bug * Improve naive pool tests * Add max attestations test * Revert changes to the op_pool * Refactor timer
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
use super::{Attestation, Domain, EthSpec, Fork, PublicKey, SecretKey, Signature, SignedRoot};
|
||||
use super::{
|
||||
Attestation, ChainSpec, Domain, EthSpec, Fork, PublicKey, SecretKey, Signature, SignedRoot,
|
||||
};
|
||||
use crate::test_utils::TestRandom;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
@@ -21,60 +23,45 @@ pub struct AggregateAndProof<T: EthSpec> {
|
||||
}
|
||||
|
||||
impl<T: EthSpec> AggregateAndProof<T> {
|
||||
pub fn is_valid_selection_proof(&self, validator_pubkey: &PublicKey, fork: &Fork) -> bool {
|
||||
/// Produces a new `AggregateAndProof` with a `selection_proof` generated by signing
|
||||
/// `aggregate.data.slot` with `secret_key`.
|
||||
pub fn from_aggregate(
|
||||
aggregator_index: u64,
|
||||
aggregate: Attestation<T>,
|
||||
secret_key: &SecretKey,
|
||||
fork: &Fork,
|
||||
spec: &ChainSpec,
|
||||
) -> Self {
|
||||
let slot = aggregate.data.slot;
|
||||
|
||||
let domain = spec.get_domain(
|
||||
slot.epoch(T::slots_per_epoch()),
|
||||
Domain::SelectionProof,
|
||||
fork,
|
||||
);
|
||||
|
||||
let message = slot.signing_root(domain);
|
||||
|
||||
Self {
|
||||
aggregator_index,
|
||||
aggregate,
|
||||
selection_proof: Signature::new(message.as_bytes(), secret_key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if `validator_pubkey` signed over `self.aggregate.data.slot`.
|
||||
pub fn is_valid_selection_proof(
|
||||
&self,
|
||||
validator_pubkey: &PublicKey,
|
||||
fork: &Fork,
|
||||
spec: &ChainSpec,
|
||||
) -> bool {
|
||||
let target_epoch = self.aggregate.data.slot.epoch(T::slots_per_epoch());
|
||||
let domain = T::default_spec().get_domain(target_epoch, Domain::SelectionProof, fork);
|
||||
let domain = spec.get_domain(target_epoch, Domain::SelectionProof, fork);
|
||||
let message = self.aggregate.data.slot.signing_root(domain);
|
||||
self.selection_proof
|
||||
.verify(message.as_bytes(), validator_pubkey)
|
||||
}
|
||||
|
||||
/// Converts Self into a SignedAggregateAndProof.
|
||||
pub fn into_signed(self, secret_key: &SecretKey, fork: &Fork) -> SignedAggregateAndProof<T> {
|
||||
let target_epoch = self.aggregate.data.slot.epoch(T::slots_per_epoch());
|
||||
let domain = T::default_spec().get_domain(target_epoch, Domain::AggregateAndProof, fork);
|
||||
let sign_message = self.signing_root(domain);
|
||||
let signature = Signature::new(sign_message.as_bytes(), &secret_key);
|
||||
|
||||
SignedAggregateAndProof {
|
||||
message: self,
|
||||
signature,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EthSpec> SignedRoot for AggregateAndProof<T> {}
|
||||
|
||||
/// A Validators signed aggregate proof to publish on the `beacon_aggregate_and_proof`
|
||||
/// gossipsub topic.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct SignedAggregateAndProof<T: EthSpec> {
|
||||
/// The `AggregateAndProof` that was signed.
|
||||
pub message: AggregateAndProof<T>,
|
||||
/// The aggregate attestation.
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> SignedRoot for SignedAggregateAndProof<T> {}
|
||||
|
||||
impl<T: EthSpec> SignedAggregateAndProof<T> {
|
||||
/// Verifies the signature of the `AggregateAndProof`
|
||||
pub fn is_valid_signature(&self, validator_pubkey: &PublicKey, fork: &Fork) -> bool {
|
||||
let target_epoch = self.message.aggregate.data.slot.epoch(T::slots_per_epoch());
|
||||
let domain = T::default_spec().get_domain(target_epoch, Domain::AggregateAndProof, fork);
|
||||
let message = self.signing_root(domain);
|
||||
self.signature.verify(message.as_bytes(), validator_pubkey)
|
||||
}
|
||||
|
||||
/// Verifies the signature of the `AggregateAndProof` as well the underlying selection_proof in
|
||||
/// the contained `AggregateAndProof`.
|
||||
pub fn is_valid(&self, validator_pubkey: &PublicKey, fork: &Fork) -> bool {
|
||||
self.is_valid_signature(validator_pubkey, fork)
|
||||
&& self
|
||||
.message
|
||||
.is_valid_selection_proof(validator_pubkey, fork)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ pub mod indexed_attestation;
|
||||
pub mod pending_attestation;
|
||||
pub mod proposer_slashing;
|
||||
pub mod relative_epoch;
|
||||
pub mod signed_aggregate_and_proof;
|
||||
pub mod signed_beacon_block;
|
||||
pub mod signed_beacon_block_header;
|
||||
pub mod signed_voluntary_exit;
|
||||
@@ -46,7 +47,7 @@ mod tree_hash_impls;
|
||||
|
||||
use ethereum_types::{H160, H256};
|
||||
|
||||
pub use crate::aggregate_and_proof::{AggregateAndProof, SignedAggregateAndProof};
|
||||
pub use crate::aggregate_and_proof::AggregateAndProof;
|
||||
pub use crate::attestation::{Attestation, Error as AttestationError};
|
||||
pub use crate::attestation_data::AttestationData;
|
||||
pub use crate::attestation_duty::AttestationDuty;
|
||||
@@ -70,6 +71,7 @@ pub use crate::indexed_attestation::IndexedAttestation;
|
||||
pub use crate::pending_attestation::PendingAttestation;
|
||||
pub use crate::proposer_slashing::ProposerSlashing;
|
||||
pub use crate::relative_epoch::{Error as RelativeEpochError, RelativeEpoch};
|
||||
pub use crate::signed_aggregate_and_proof::SignedAggregateAndProof;
|
||||
pub use crate::signed_beacon_block::SignedBeaconBlock;
|
||||
pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader;
|
||||
pub use crate::signed_voluntary_exit::SignedVoluntaryExit;
|
||||
|
||||
68
eth2/types/src/signed_aggregate_and_proof.rs
Normal file
68
eth2/types/src/signed_aggregate_and_proof.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use super::{
|
||||
AggregateAndProof, Attestation, ChainSpec, Domain, EthSpec, Fork, PublicKey, SecretKey,
|
||||
Signature, SignedRoot,
|
||||
};
|
||||
use crate::test_utils::TestRandom;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use test_random_derive::TestRandom;
|
||||
use tree_hash_derive::TreeHash;
|
||||
|
||||
/// A Validators signed aggregate proof to publish on the `beacon_aggregate_and_proof`
|
||||
/// gossipsub topic.
|
||||
///
|
||||
/// Spec v0.10.1
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode, TestRandom, TreeHash)]
|
||||
#[serde(bound = "T: EthSpec")]
|
||||
pub struct SignedAggregateAndProof<T: EthSpec> {
|
||||
/// The `AggregateAndProof` that was signed.
|
||||
pub message: AggregateAndProof<T>,
|
||||
/// The aggregate attestation.
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
impl<T: EthSpec> SignedAggregateAndProof<T> {
|
||||
/// Produces a new `SignedAggregateAndProof` with a `selection_proof` generated by signing
|
||||
/// `aggregate.data.slot` with `secret_key`.
|
||||
pub fn from_aggregate(
|
||||
aggregator_index: u64,
|
||||
aggregate: Attestation<T>,
|
||||
secret_key: &SecretKey,
|
||||
fork: &Fork,
|
||||
spec: &ChainSpec,
|
||||
) -> Self {
|
||||
let message =
|
||||
AggregateAndProof::from_aggregate(aggregator_index, aggregate, secret_key, fork, spec);
|
||||
|
||||
let target_epoch = message.aggregate.data.slot.epoch(T::slots_per_epoch());
|
||||
let domain = spec.get_domain(target_epoch, Domain::AggregateAndProof, fork);
|
||||
let signing_message = message.signing_root(domain);
|
||||
|
||||
SignedAggregateAndProof {
|
||||
message,
|
||||
signature: Signature::new(signing_message.as_bytes(), &secret_key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the signature of the `AggregateAndProof`
|
||||
pub fn is_valid_signature(
|
||||
&self,
|
||||
validator_pubkey: &PublicKey,
|
||||
fork: &Fork,
|
||||
spec: &ChainSpec,
|
||||
) -> bool {
|
||||
let target_epoch = self.message.aggregate.data.slot.epoch(T::slots_per_epoch());
|
||||
let domain = spec.get_domain(target_epoch, Domain::AggregateAndProof, fork);
|
||||
let message = self.message.signing_root(domain);
|
||||
self.signature.verify(message.as_bytes(), validator_pubkey)
|
||||
}
|
||||
|
||||
/// Verifies the signature of the `AggregateAndProof` as well the underlying selection_proof in
|
||||
/// the contained `AggregateAndProof`.
|
||||
pub fn is_valid(&self, validator_pubkey: &PublicKey, fork: &Fork, spec: &ChainSpec) -> bool {
|
||||
self.is_valid_signature(validator_pubkey, fork, spec)
|
||||
&& self
|
||||
.message
|
||||
.is_valid_selection_proof(validator_pubkey, fork, spec)
|
||||
}
|
||||
}
|
||||
@@ -12,4 +12,4 @@ pub use generate_deterministic_keypairs::load_keypairs_from_yaml;
|
||||
pub use keypairs_file::KeypairsFile;
|
||||
pub use rand::{RngCore, SeedableRng};
|
||||
pub use rand_xorshift::XorShiftRng;
|
||||
pub use test_random::TestRandom;
|
||||
pub use test_random::{test_random_instance, TestRandom};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use crate::*;
|
||||
use rand::RngCore;
|
||||
use rand::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use ssz_types::typenum::Unsigned;
|
||||
|
||||
mod address;
|
||||
@@ -12,6 +14,11 @@ mod secret_key;
|
||||
mod signature;
|
||||
mod signature_bytes;
|
||||
|
||||
pub fn test_random_instance<T: TestRandom>() -> T {
|
||||
let mut rng = XorShiftRng::from_seed([0x42; 16]);
|
||||
T::random_for_test(&mut rng)
|
||||
}
|
||||
|
||||
pub trait TestRandom {
|
||||
fn random_for_test(rng: &mut impl RngCore) -> Self;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user