Merge branch 'master' into blop-pool

This commit is contained in:
Paul Hauner
2019-03-29 17:49:33 +11:00
76 changed files with 4435 additions and 787 deletions

View File

@@ -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_data(slot, shard)? {
let attestation_data = match self.beacon_node.produce_attestation(slot, shard)? {
Some(attestation_data) => attestation_data,
None => return Ok(PollOutcome::BeaconNodeUnableToProduceAttestation(slot)),
};
@@ -119,8 +119,7 @@ impl<T: SlotClock, U: BeaconNode, V: DutiesReader, W: Signer> Attester<T, U, V,
validator_index,
};
self.beacon_node
.publish_attestation_data(free_attestation)?;
self.beacon_node.publish_attestation(free_attestation)?;
Ok(PollOutcome::AttestationProduced(slot))
}

View File

@@ -26,7 +26,7 @@ impl SimulatedBeaconNode {
}
impl BeaconNode for SimulatedBeaconNode {
fn produce_attestation_data(&self, slot: Slot, shard: u64) -> ProduceResult {
fn produce_attestation(&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(),
@@ -34,7 +34,7 @@ impl BeaconNode for SimulatedBeaconNode {
}
}
fn publish_attestation_data(&self, free_attestation: FreeAttestation) -> PublishResult {
fn publish_attestation(&self, free_attestation: FreeAttestation) -> PublishResult {
*self.publish_input.write().unwrap() = Some(free_attestation.clone());
match *self.publish_result.read().unwrap() {
Some(ref r) => r.clone(),

View File

@@ -14,13 +14,13 @@ pub enum PublishOutcome {
/// Defines the methods required to produce and publish blocks on a Beacon Node.
pub trait BeaconNode: Send + Sync {
fn produce_attestation_data(
fn produce_attestation(
&self,
slot: Slot,
shard: u64,
) -> Result<Option<AttestationData>, BeaconNodeError>;
fn publish_attestation_data(
fn publish_attestation(
&self,
free_attestation: FreeAttestation,
) -> Result<PublishOutcome, BeaconNodeError>;

View File

@@ -20,7 +20,6 @@ pub fn per_slot_processing(
if (state.slot + 1) % spec.slots_per_epoch == 0 {
per_epoch_processing(state, spec)?;
state.advance_caches();
}
state.slot += 1;

View File

@@ -26,7 +26,7 @@ ssz = { path = "../utils/ssz" }
ssz_derive = { path = "../utils/ssz_derive" }
swap_or_not_shuffle = { path = "../utils/swap_or_not_shuffle" }
test_random_derive = { path = "../utils/test_random_derive" }
libp2p = { git = "https://github.com/SigP/rust-libp2p", branch = "gossipsub" }
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b3c32d9a821ae6cc89079499cc6e8a6bab0bffc3" }
[dev-dependencies]
env_logger = "0.6.0"

View File

@@ -37,6 +37,19 @@ impl BeaconBlockHeader {
pub fn canonical_root(&self) -> Hash256 {
Hash256::from_slice(&self.hash_tree_root()[..])
}
/// Given a `body`, consumes `self` and returns a complete `BeaconBlock`.
///
/// Spec v0.5.0
pub fn into_block(self, body: BeaconBlockBody) -> BeaconBlock {
BeaconBlock {
slot: self.slot,
previous_block_root: self.previous_block_root,
state_root: self.state_root,
body,
signature: self.signature,
}
}
}
#[cfg(test)]

View File

@@ -120,7 +120,7 @@ pub struct ChainSpec {
*
*/
pub boot_nodes: Vec<Multiaddr>,
pub network_id: u8,
pub chain_id: u8,
}
impl ChainSpec {
@@ -257,7 +257,7 @@ impl ChainSpec {
* Boot nodes
*/
boot_nodes: vec![],
network_id: 1, // foundation network id
chain_id: 1, // foundation chain id
}
}
@@ -274,7 +274,7 @@ impl ChainSpec {
Self {
boot_nodes,
network_id: 2, // lighthouse testnet network id
chain_id: 2, // lighthouse testnet chain id
..ChainSpec::few_validators()
}
}

View File

@@ -85,6 +85,6 @@ pub type AttesterMap = HashMap<(u64, u64), Vec<usize>>;
pub type ProposerMap = HashMap<u64, usize>;
pub use bls::{AggregatePublicKey, AggregateSignature, Keypair, PublicKey, SecretKey, Signature};
pub use libp2p::floodsub::{Topic, TopicBuilder};
pub use libp2p::floodsub::{Topic, TopicBuilder, TopicHash};
pub use libp2p::multiaddr;
pub use libp2p::Multiaddr;

View File

@@ -23,6 +23,7 @@ pub fn keypairs_path() -> PathBuf {
/// Builds a beacon state to be used for testing purposes.
///
/// This struct should **never be used for production purposes.**
#[derive(Clone)]
pub struct TestingBeaconStateBuilder {
state: BeaconState,
keypairs: Vec<Keypair>,
@@ -119,8 +120,10 @@ impl TestingBeaconStateBuilder {
})
.collect();
let genesis_time = 1553753928; // arbitrary
let mut state = BeaconState::genesis(
0,
genesis_time,
Eth1Data {
deposit_root: Hash256::zero(),
block_hash: Hash256::zero(),

View File

@@ -0,0 +1,117 @@
use super::{fake_signature::FakeSignature, AggregatePublicKey};
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use serde_hex::{encode as hex_encode, PrefixedHexVisitor};
use ssz::{
decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
};
const SIGNATURE_LENGTH: usize = 48;
/// A BLS aggregate signature.
///
/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ
/// serialization).
#[derive(Debug, PartialEq, Clone, Default, Eq)]
pub struct FakeAggregateSignature {
bytes: Vec<u8>,
}
impl FakeAggregateSignature {
/// Creates a new all-zero's signature
pub fn new() -> Self {
Self::zero()
}
/// Creates a new all-zero's signature
pub fn zero() -> Self {
Self {
bytes: vec![0; SIGNATURE_LENGTH],
}
}
/// Does glorious nothing.
pub fn add(&mut self, _signature: &FakeSignature) {
// Do nothing.
}
/// _Always_ returns `true`.
pub fn verify(
&self,
_msg: &[u8],
_domain: u64,
_aggregate_public_key: &AggregatePublicKey,
) -> bool {
true
}
/// _Always_ returns `true`.
pub fn verify_multiple(
&self,
_messages: &[&[u8]],
_domain: u64,
_aggregate_public_keys: &[&AggregatePublicKey],
) -> bool {
true
}
}
impl Encodable for FakeAggregateSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.bytes);
}
}
impl Decodable for FakeAggregateSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
Ok((FakeAggregateSignature { bytes: sig_bytes }, i))
}
}
impl Serialize for FakeAggregateSignature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&hex_encode(ssz_encode(self)))
}
}
impl<'de> Deserialize<'de> for FakeAggregateSignature {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(PrefixedHexVisitor)?;
let (obj, _) = <_>::ssz_decode(&bytes[..], 0)
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(obj)
}
}
impl TreeHash for FakeAggregateSignature {
fn hash_tree_root(&self) -> Vec<u8> {
hash(&self.bytes)
}
}
#[cfg(test)]
mod tests {
use super::super::{Keypair, Signature};
use super::*;
use ssz::ssz_encode;
#[test]
pub fn test_ssz_round_trip() {
let keypair = Keypair::random();
let mut original = FakeAggregateSignature::new();
original.add(&Signature::new(&[42, 42], 0, &keypair.sk));
let bytes = ssz_encode(&original);
let (decoded, _) = FakeAggregateSignature::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@@ -0,0 +1,117 @@
use super::serde_vistors::HexVisitor;
use super::{PublicKey, SecretKey};
use hex::encode as hex_encode;
use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use ssz::{
decode_ssz_list, hash, ssz_encode, Decodable, DecodeError, Encodable, SszStream, TreeHash,
};
const SIGNATURE_LENGTH: usize = 48;
/// A single BLS signature.
///
/// This struct is a wrapper upon a base type and provides helper functions (e.g., SSZ
/// serialization).
#[derive(Debug, PartialEq, Clone, Eq)]
pub struct FakeSignature {
bytes: Vec<u8>,
}
impl FakeSignature {
/// Creates a new all-zero's signature
pub fn new(_msg: &[u8], _domain: u64, _sk: &SecretKey) -> Self {
FakeSignature::zero()
}
/// Creates a new all-zero's signature
pub fn zero() -> Self {
Self {
bytes: vec![0; SIGNATURE_LENGTH],
}
}
/// Creates a new all-zero's signature
pub fn new_hashed(_x_real_hashed: &[u8], _x_imaginary_hashed: &[u8], _sk: &SecretKey) -> Self {
FakeSignature::zero()
}
/// _Always_ returns `true`.
pub fn verify(&self, _msg: &[u8], _domain: u64, _pk: &PublicKey) -> bool {
true
}
/// _Always_ returns true.
pub fn verify_hashed(
&self,
_x_real_hashed: &[u8],
_x_imaginary_hashed: &[u8],
_pk: &PublicKey,
) -> bool {
true
}
/// Returns a new empty signature.
pub fn empty_signature() -> Self {
FakeSignature::zero()
}
}
impl Encodable for FakeSignature {
fn ssz_append(&self, s: &mut SszStream) {
s.append_vec(&self.bytes);
}
}
impl Decodable for FakeSignature {
fn ssz_decode(bytes: &[u8], i: usize) -> Result<(Self, usize), DecodeError> {
let (sig_bytes, i) = decode_ssz_list(bytes, i)?;
Ok((FakeSignature { bytes: sig_bytes }, i))
}
}
impl TreeHash for FakeSignature {
fn hash_tree_root(&self) -> Vec<u8> {
hash(&self.bytes)
}
}
impl Serialize for FakeSignature {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&hex_encode(ssz_encode(self)))
}
}
impl<'de> Deserialize<'de> for FakeSignature {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let bytes = deserializer.deserialize_str(HexVisitor)?;
let (pubkey, _) = <_>::ssz_decode(&bytes[..], 0)
.map_err(|e| serde::de::Error::custom(format!("invalid ssz ({:?})", e)))?;
Ok(pubkey)
}
}
#[cfg(test)]
mod tests {
use super::super::Keypair;
use super::*;
use ssz::ssz_encode;
#[test]
pub fn test_ssz_round_trip() {
let keypair = Keypair::random();
let original = FakeSignature::new(&[42, 42], 0, &keypair.sk);
let bytes = ssz_encode(&original);
let (decoded, _) = FakeSignature::ssz_decode(&bytes, 0).unwrap();
assert_eq!(original, decoded);
}
}

View File

@@ -14,4 +14,8 @@ impl Keypair {
let pk = PublicKey::from_secret_key(&sk);
Keypair { sk, pk }
}
pub fn identifier(&self) -> String {
self.pk.concatenated_hex_id()
}
}

View File

@@ -2,19 +2,33 @@ extern crate bls_aggregates;
extern crate ssz;
mod aggregate_public_key;
mod aggregate_signature;
mod keypair;
mod public_key;
mod secret_key;
mod serde_vistors;
#[cfg(not(debug_assertions))]
mod aggregate_signature;
#[cfg(not(debug_assertions))]
mod signature;
#[cfg(not(debug_assertions))]
pub use crate::aggregate_signature::AggregateSignature;
#[cfg(not(debug_assertions))]
pub use crate::signature::Signature;
#[cfg(debug_assertions)]
mod fake_aggregate_signature;
#[cfg(debug_assertions)]
mod fake_signature;
#[cfg(debug_assertions)]
pub use crate::fake_aggregate_signature::FakeAggregateSignature as AggregateSignature;
#[cfg(debug_assertions)]
pub use crate::fake_signature::FakeSignature as Signature;
pub use crate::aggregate_public_key::AggregatePublicKey;
pub use crate::aggregate_signature::AggregateSignature;
pub use crate::keypair::Keypair;
pub use crate::public_key::PublicKey;
pub use crate::secret_key::SecretKey;
pub use crate::signature::Signature;
pub const BLS_AGG_SIG_BYTE_SIZE: usize = 96;

View File

@@ -3,10 +3,13 @@ mod testing_slot_clock;
pub use crate::system_time_slot_clock::{Error as SystemTimeSlotClockError, SystemTimeSlotClock};
pub use crate::testing_slot_clock::{Error as TestingSlotClockError, TestingSlotClock};
use std::time::Duration;
pub use types::Slot;
pub trait SlotClock: Send + Sync {
type Error;
fn present_slot(&self) -> Result<Option<Slot>, Self::Error>;
fn duration_to_next_slot(&self) -> Result<Option<Duration>, Self::Error>;
}

View File

@@ -13,6 +13,7 @@ pub enum Error {
/// Determines the present slot based upon the present system time.
#[derive(Clone)]
pub struct SystemTimeSlotClock {
genesis_slot: Slot,
genesis_seconds: u64,
slot_duration_seconds: u64,
}
@@ -22,6 +23,7 @@ impl SystemTimeSlotClock {
///
/// Returns an Error if `slot_duration_seconds == 0`.
pub fn new(
genesis_slot: Slot,
genesis_seconds: u64,
slot_duration_seconds: u64,
) -> Result<SystemTimeSlotClock, Error> {
@@ -29,6 +31,7 @@ impl SystemTimeSlotClock {
Err(Error::SlotDurationIsZero)
} else {
Ok(Self {
genesis_slot,
genesis_seconds,
slot_duration_seconds,
})
@@ -44,11 +47,17 @@ impl SlotClock for SystemTimeSlotClock {
let duration_since_epoch = syslot_time.duration_since(SystemTime::UNIX_EPOCH)?;
let duration_since_genesis =
duration_since_epoch.checked_sub(Duration::from_secs(self.genesis_seconds));
match duration_since_genesis {
None => Ok(None),
Some(d) => Ok(slot_from_duration(self.slot_duration_seconds, d)),
Some(d) => Ok(slot_from_duration(self.slot_duration_seconds, d)
.and_then(|s| Some(s + self.genesis_slot))),
}
}
fn duration_to_next_slot(&self) -> Result<Option<Duration>, Error> {
duration_to_next_slot(self.genesis_seconds, self.slot_duration_seconds)
}
}
impl From<SystemTimeError> for Error {
@@ -62,6 +71,30 @@ fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option<
duration.as_secs().checked_div(slot_duration_seconds)?,
))
}
// calculate the duration to the next slot
fn duration_to_next_slot(
genesis_time: u64,
seconds_per_slot: u64,
) -> Result<Option<Duration>, Error> {
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
let genesis_time = Duration::from_secs(genesis_time);
if now < genesis_time {
return Ok(None);
}
let since_genesis = now - genesis_time;
let elapsed_slots = since_genesis.as_secs() / seconds_per_slot;
let next_slot_start_seconds = (elapsed_slots + 1)
.checked_mul(seconds_per_slot)
.expect("Next slot time should not overflow u64");
let time_to_next_slot = Duration::from_secs(next_slot_start_seconds) - since_genesis;
Ok(Some(time_to_next_slot))
}
#[cfg(test)]
mod tests {
@@ -74,6 +107,7 @@ mod tests {
#[test]
fn test_slot_now() {
let slot_time = 100;
let genesis_slot = Slot::new(0);
let now = SystemTime::now();
let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap();
@@ -81,18 +115,21 @@ mod tests {
let genesis = since_epoch.as_secs() - slot_time * 89;
let clock = SystemTimeSlotClock {
genesis_slot,
genesis_seconds: genesis,
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(Slot::new(89)));
let clock = SystemTimeSlotClock {
genesis_slot,
genesis_seconds: since_epoch.as_secs(),
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(Slot::new(0)));
let clock = SystemTimeSlotClock {
genesis_slot,
genesis_seconds: since_epoch.as_secs() - slot_time * 42 - 5,
slot_duration_seconds: slot_time,
};

View File

@@ -1,5 +1,6 @@
use super::SlotClock;
use std::sync::RwLock;
use std::time::Duration;
use types::Slot;
#[derive(Debug, PartialEq)]
@@ -32,6 +33,11 @@ impl SlotClock for TestingSlotClock {
let slot = *self.slot.read().expect("TestingSlotClock poisoned.");
Ok(Some(Slot::new(slot)))
}
/// Always returns a duration of 1 second.
fn duration_to_next_slot(&self) -> Result<Option<Duration>, Error> {
Ok(Some(Duration::from_secs(1)))
}
}
#[cfg(test)]