mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-19 21:04:41 +00:00
Merge branch 'validator-enhancements' into testnet-client
This commit is contained in:
@@ -94,7 +94,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> Attester<T, U, V,
|
||||
}
|
||||
|
||||
fn produce_attestation(&mut self, slot: Slot, shard: u64) -> Result<PollOutcome, Error> {
|
||||
let attestation_data = match self.beacon_node.produce_attestation(slot, shard)? {
|
||||
let attestation_data = match self.beacon_node.produce_attestation_data(slot, shard)? {
|
||||
Some(attestation_data) => attestation_data,
|
||||
None => return Ok(PollOutcome::BeaconNodeUnableToProduceAttestation(slot)),
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ impl SimulatedBeaconNode {
|
||||
}
|
||||
|
||||
impl BeaconNode for SimulatedBeaconNode {
|
||||
fn produce_attestation(&self, slot: Slot, shard: u64) -> ProduceResult {
|
||||
fn produce_attestation_data(&self, slot: Slot, shard: u64) -> ProduceResult {
|
||||
*self.produce_input.write().unwrap() = Some((slot, shard));
|
||||
match *self.produce_result.read().unwrap() {
|
||||
Some(ref r) => r.clone(),
|
||||
|
||||
@@ -14,7 +14,7 @@ pub enum PublishOutcome {
|
||||
|
||||
/// Defines the methods required to produce and publish blocks on a Beacon Node.
|
||||
pub trait BeaconNode: Send + Sync {
|
||||
fn produce_attestation(
|
||||
fn produce_attestation_data(
|
||||
&self,
|
||||
slot: Slot,
|
||||
shard: u64,
|
||||
|
||||
@@ -183,6 +183,8 @@ impl OperationPool {
|
||||
|| key.domain_bytes_match(&curr_domain_bytes)
|
||||
})
|
||||
.flat_map(|(_, attestations)| attestations)
|
||||
// That are not superseded by an attestation included in the state...
|
||||
.filter(|attestation| !superior_attestation_exists_in_state(state, attestation))
|
||||
// That are valid...
|
||||
.filter(|attestation| validate_attestation(state, attestation, spec).is_ok())
|
||||
// Scored by the number of new attestations they introduce (descending)
|
||||
@@ -475,6 +477,31 @@ impl OperationPool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the state already contains a `PendingAttestation` that is superior to the
|
||||
/// given `attestation`.
|
||||
///
|
||||
/// A validator has nothing to gain from re-including an attestation and it adds load to the
|
||||
/// network.
|
||||
///
|
||||
/// An existing `PendingAttestation` is superior to an existing `attestation` if:
|
||||
///
|
||||
/// - Their `AttestationData` is equal.
|
||||
/// - `attestation` does not contain any signatures that `PendingAttestation` does not have.
|
||||
fn superior_attestation_exists_in_state(state: &BeaconState, attestation: &Attestation) -> bool {
|
||||
state
|
||||
.current_epoch_attestations
|
||||
.iter()
|
||||
.chain(state.previous_epoch_attestations.iter())
|
||||
.any(|existing_attestation| {
|
||||
let bitfield = &attestation.aggregation_bitfield;
|
||||
let existing_bitfield = &existing_attestation.aggregation_bitfield;
|
||||
|
||||
existing_attestation.data == attestation.data
|
||||
&& bitfield.intersection(existing_bitfield).num_set_bits()
|
||||
== bitfield.num_set_bits()
|
||||
})
|
||||
}
|
||||
|
||||
/// Filter up to a maximum number of operations out of an iterator.
|
||||
fn filter_limit_operations<'a, T: 'a, I, F>(operations: I, filter: F, limit: u64) -> Vec<T>
|
||||
where
|
||||
|
||||
@@ -227,7 +227,7 @@ impl ValidatorStatuses {
|
||||
status.is_previous_epoch_attester = true;
|
||||
|
||||
// The inclusion slot and distance are only required for previous epoch attesters.
|
||||
let relative_epoch = RelativeEpoch::from_slot(state.slot, a.data.slot, spec)?;
|
||||
let relative_epoch = RelativeEpoch::from_slot(state.slot, a.inclusion_slot, spec)?;
|
||||
status.inclusion_info = Some(InclusionInfo {
|
||||
slot: a.inclusion_slot,
|
||||
distance: inclusion_distance(a),
|
||||
|
||||
@@ -661,6 +661,17 @@ impl BeaconState {
|
||||
})
|
||||
}
|
||||
|
||||
/// Build all the caches, if they need to be built.
|
||||
pub fn build_all_caches(&mut self, spec: &ChainSpec) -> Result<(), Error> {
|
||||
self.build_epoch_cache(RelativeEpoch::Previous, spec)?;
|
||||
self.build_epoch_cache(RelativeEpoch::Current, spec)?;
|
||||
self.build_epoch_cache(RelativeEpoch::NextWithoutRegistryChange, spec)?;
|
||||
self.build_epoch_cache(RelativeEpoch::NextWithRegistryChange, spec)?;
|
||||
self.update_pubkey_cache()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Build an epoch cache, unless it is has already been built.
|
||||
pub fn build_epoch_cache(
|
||||
&mut self,
|
||||
|
||||
@@ -113,6 +113,16 @@ mod epoch_tests {
|
||||
|
||||
all_tests!(Epoch);
|
||||
|
||||
#[test]
|
||||
fn epoch_start_end() {
|
||||
let slots_per_epoch = 8;
|
||||
|
||||
let epoch = Epoch::new(0);
|
||||
|
||||
assert_eq!(epoch.start_slot(slots_per_epoch), Slot::new(0));
|
||||
assert_eq!(epoch.end_slot(slots_per_epoch), Slot::new(7));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slot_iter() {
|
||||
let slots_per_epoch = 8;
|
||||
|
||||
@@ -6,6 +6,8 @@ use dirs;
|
||||
use log::debug;
|
||||
use rayon::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
//TODO: testing only
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
pub const KEYPAIRS_FILE: &str = "keypairs.raw_keypairs";
|
||||
|
||||
@@ -120,7 +122,17 @@ impl TestingBeaconStateBuilder {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let genesis_time = 1553753928; // arbitrary
|
||||
// TODO: Testing only. Burn with fire later.
|
||||
// set genesis to the last 30 minute block.
|
||||
// this is used for testing only. Allows multiple nodes to connect within a 30min window
|
||||
// and agree on a genesis
|
||||
let now = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
let secs_after_last_period = now.checked_rem(30 * 60).unwrap_or(0);
|
||||
// genesis is now the last 30 minute block.
|
||||
let genesis_time = now - secs_after_last_period;
|
||||
|
||||
let mut state = BeaconState::genesis(
|
||||
genesis_time,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use super::{PublicKey, SecretKey};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Keypair {
|
||||
@@ -19,3 +21,21 @@ impl Keypair {
|
||||
self.pk.concatenated_hex_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Keypair {
|
||||
/// Note: this is distinct from consensus serialization, it will produce a different hash.
|
||||
///
|
||||
/// This method uses the uncompressed bytes, which are much faster to obtain than the
|
||||
/// compressed bytes required for consensus serialization.
|
||||
///
|
||||
/// Use `ssz::Encode` to obtain the bytes required for consensus hashing.
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.pk.as_uncompressed_bytes().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Keypair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.pk)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use serde::ser::{Serialize, Serializer};
|
||||
use serde_hex::{encode as hex_encode, HexVisitor};
|
||||
use ssz::{decode, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash};
|
||||
use std::default;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// A single BLS signature.
|
||||
@@ -52,6 +53,12 @@ impl PublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PublicKey {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.concatenated_hex_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl default::Default for PublicKey {
|
||||
fn default() -> Self {
|
||||
let secret_key = SecretKey::random();
|
||||
|
||||
Reference in New Issue
Block a user