Updates to latest interop branch.

- Shifts decoding of objects into message handler.
- Updates to latest interop gossipsub.
- Adds interop spec constant.
This commit is contained in:
Age Manning 2019-08-06 17:54:38 +10:00
parent 0613bc16fc
commit 107bbdcccd
No known key found for this signature in database
GPG Key ID: 05EED64B79E06A93
16 changed files with 199 additions and 157 deletions

View File

@ -7,8 +7,8 @@ edition = "2018"
[dependencies] [dependencies]
clap = "2.32.0" clap = "2.32.0"
#SigP repository #SigP repository
libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "35104cca27231b9178e1fea5b3788ea41ba8af76" } libp2p = { git = "https://github.com/SigP/rust-libp2p", rev = "b0d3cf7b4b0fa6c555b64dbdd110673a05457abd" }
enr = { git = "https://github.com/SigP/rust-libp2p/", rev = "35104cca27231b9178e1fea5b3788ea41ba8af76", features = ["serde"] } enr = { git = "https://github.com/SigP/rust-libp2p/", rev = "b0d3cf7b4b0fa6c555b64dbdd110673a05457abd", features = ["serde"] }
types = { path = "../../eth2/types" } types = { path = "../../eth2/types" }
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"

View File

@ -2,6 +2,7 @@ use crate::discovery::Discovery;
use crate::rpc::{RPCEvent, RPCMessage, RPC}; use crate::rpc::{RPCEvent, RPCMessage, RPC};
use crate::{error, NetworkConfig}; use crate::{error, NetworkConfig};
use crate::{Topic, TopicHash}; use crate::{Topic, TopicHash};
use crate::{BEACON_ATTESTATION_TOPIC, BEACON_BLOCK_TOPIC};
use futures::prelude::*; use futures::prelude::*;
use libp2p::{ use libp2p::{
core::identity::Keypair, core::identity::Keypair,
@ -13,11 +14,10 @@ use libp2p::{
tokio_io::{AsyncRead, AsyncWrite}, tokio_io::{AsyncRead, AsyncWrite},
NetworkBehaviour, PeerId, NetworkBehaviour, PeerId,
}; };
use slog::{debug, o, trace, warn}; use slog::{debug, o, trace};
use ssz::{ssz_encode, Decode, DecodeError, Encode}; use ssz::{ssz_encode, Encode};
use std::num::NonZeroU32; use std::num::NonZeroU32;
use std::time::Duration; use std::time::Duration;
use types::{Attestation, BeaconBlock};
/// Builds the network behaviour that manages the core protocols of eth2. /// Builds the network behaviour that manages the core protocols of eth2.
/// This core behaviour is managed by `Behaviour` which adds peer management to all core /// This core behaviour is managed by `Behaviour` which adds peer management to all core
@ -87,23 +87,12 @@ impl<TSubstream: AsyncRead + AsyncWrite> NetworkBehaviourEventProcess<GossipsubE
GossipsubEvent::Message(gs_msg) => { GossipsubEvent::Message(gs_msg) => {
trace!(self.log, "Received GossipEvent"; "msg" => format!("{:?}", gs_msg)); trace!(self.log, "Received GossipEvent"; "msg" => format!("{:?}", gs_msg));
let pubsub_message = match PubsubMessage::from_ssz_bytes(&gs_msg.data) { let msg = PubsubMessage::from_topics(&gs_msg.topics, gs_msg.data);
//TODO: Punish peer on error
Err(e) => {
warn!(
self.log,
"Received undecodable message from Peer {:?} error", gs_msg.source;
"error" => format!("{:?}", e)
);
return;
}
Ok(msg) => msg,
};
self.events.push(BehaviourEvent::GossipMessage { self.events.push(BehaviourEvent::GossipMessage {
source: gs_msg.source, source: gs_msg.source,
topics: gs_msg.topics, topics: gs_msg.topics,
message: Box::new(pubsub_message), message: msg,
}); });
} }
GossipsubEvent::Subscribed { .. } => {} GossipsubEvent::Subscribed { .. } => {}
@ -225,7 +214,7 @@ pub enum BehaviourEvent {
GossipMessage { GossipMessage {
source: PeerId, source: PeerId,
topics: Vec<TopicHash>, topics: Vec<TopicHash>,
message: Box<PubsubMessage>, message: PubsubMessage,
}, },
} }
@ -233,41 +222,50 @@ pub enum BehaviourEvent {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum PubsubMessage { pub enum PubsubMessage {
/// Gossipsub message providing notification of a new block. /// Gossipsub message providing notification of a new block.
Block(BeaconBlock), Block(Vec<u8>),
/// Gossipsub message providing notification of a new attestation. /// Gossipsub message providing notification of a new attestation.
Attestation(Attestation), Attestation(Vec<u8>),
/// Gossipsub message from an unknown topic.
Unknown(Vec<u8>),
}
impl PubsubMessage {
/* Note: This is assuming we are not hashing topics. If we choose to hash topics, these will
* need to be modified.
*
* Also note that a message can be associated with many topics. As soon as one of the topics is
* known we match. If none of the topics are known we return an unknown state.
*/
fn from_topics(topics: &Vec<TopicHash>, data: Vec<u8>) -> Self {
for topic in topics {
match topic.as_str() {
BEACON_BLOCK_TOPIC => return PubsubMessage::Block(data),
BEACON_ATTESTATION_TOPIC => return PubsubMessage::Attestation(data),
_ => {}
}
}
PubsubMessage::Unknown(data)
}
} }
//TODO: Correctly encode/decode enums. Prefixing with integer for now.
impl Encode for PubsubMessage { impl Encode for PubsubMessage {
fn is_ssz_fixed_len() -> bool { fn is_ssz_fixed_len() -> bool {
false false
} }
fn ssz_append(&self, buf: &mut Vec<u8>) { fn ssz_append(&self, buf: &mut Vec<u8>) {
let offset = <u32 as Encode>::ssz_fixed_len() + <Vec<u8> as Encode>::ssz_fixed_len();
let mut encoder = ssz::SszEncoder::container(buf, offset);
match self { match self {
PubsubMessage::Block(block_gossip) => { PubsubMessage::Block(inner)
encoder.append(&0_u32); | PubsubMessage::Attestation(inner)
| PubsubMessage::Unknown(inner) => {
// Encode the gossip as a Vec<u8>; // Encode the gossip as a Vec<u8>;
encoder.append(&block_gossip.as_ssz_bytes()); buf.append(&mut inner.as_ssz_bytes());
}
PubsubMessage::Attestation(attestation_gossip) => {
encoder.append(&1_u32);
// Encode the gossip as a Vec<u8>;
encoder.append(&attestation_gossip.as_ssz_bytes());
} }
} }
encoder.finalize();
} }
} }
/*
impl Decode for PubsubMessage { impl Decode for PubsubMessage {
fn is_ssz_fixed_len() -> bool { fn is_ssz_fixed_len() -> bool {
false false
@ -295,7 +293,9 @@ impl Decode for PubsubMessage {
} }
} }
} }
*/
/*
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -313,4 +313,6 @@ mod test {
assert_eq!(original, decoded); assert_eq!(original, decoded);
} }
} }
*/

View File

@ -7,7 +7,7 @@ use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
/// The beacon node topic string to subscribe to. /// The beacon node topic string to subscribe to.
pub const BEACON_PUBSUB_TOPIC: &str = "beacon_block"; pub const BEACON_BLOCK_TOPIC: &str = "beacon_block";
pub const BEACON_ATTESTATION_TOPIC: &str = "beacon_attestation"; pub const BEACON_ATTESTATION_TOPIC: &str = "beacon_attestation";
pub const SHARD_TOPIC_PREFIX: &str = "shard"; pub const SHARD_TOPIC_PREFIX: &str = "shard";

View File

@ -11,7 +11,7 @@ mod service;
pub use behaviour::PubsubMessage; pub use behaviour::PubsubMessage;
pub use config::{ pub use config::{
Config as NetworkConfig, BEACON_ATTESTATION_TOPIC, BEACON_PUBSUB_TOPIC, SHARD_TOPIC_PREFIX, Config as NetworkConfig, BEACON_ATTESTATION_TOPIC, BEACON_BLOCK_TOPIC, SHARD_TOPIC_PREFIX,
}; };
pub use libp2p::gossipsub::{Topic, TopicHash}; pub use libp2p::gossipsub::{Topic, TopicHash};
pub use libp2p::multiaddr; pub use libp2p::multiaddr;

View File

@ -12,16 +12,14 @@ use libp2p::swarm::protocols_handler::{
use smallvec::SmallVec; use smallvec::SmallVec;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use types::EthSpec;
/// The time (in seconds) before a substream that is awaiting a response times out. /// The time (in seconds) before a substream that is awaiting a response times out.
pub const RESPONSE_TIMEOUT: u64 = 9; pub const RESPONSE_TIMEOUT: u64 = 9;
/// Implementation of `ProtocolsHandler` for the RPC protocol. /// Implementation of `ProtocolsHandler` for the RPC protocol.
pub struct RPCHandler<TSubstream, E> pub struct RPCHandler<TSubstream>
where where
TSubstream: AsyncRead + AsyncWrite, TSubstream: AsyncRead + AsyncWrite,
E: EthSpec,
{ {
/// The upgrade for inbound substreams. /// The upgrade for inbound substreams.
listen_protocol: SubstreamProtocol<RPCProtocol>, listen_protocol: SubstreamProtocol<RPCProtocol>,
@ -56,8 +54,8 @@ where
/// After the given duration has elapsed, an inactive connection will shutdown. /// After the given duration has elapsed, an inactive connection will shutdown.
inactive_timeout: Duration, inactive_timeout: Duration,
/// Phantom EthSpec. /// Marker to pin the generic stream.
_phantom: PhantomData<E>, _phantom: PhantomData<TSubstream>,
} }
/// An outbound substream is waiting a response from the user. /// An outbound substream is waiting a response from the user.
@ -90,10 +88,9 @@ where
}, },
} }
impl<TSubstream, E> RPCHandler<TSubstream, E> impl<TSubstream> RPCHandler<TSubstream>
where where
TSubstream: AsyncRead + AsyncWrite, TSubstream: AsyncRead + AsyncWrite,
E: EthSpec,
{ {
pub fn new( pub fn new(
listen_protocol: SubstreamProtocol<RPCProtocol>, listen_protocol: SubstreamProtocol<RPCProtocol>,
@ -145,20 +142,18 @@ where
} }
} }
impl<TSubstream, E> Default for RPCHandler<TSubstream, E> impl<TSubstream> Default for RPCHandler<TSubstream>
where where
TSubstream: AsyncRead + AsyncWrite, TSubstream: AsyncRead + AsyncWrite,
E: EthSpec,
{ {
fn default() -> Self { fn default() -> Self {
RPCHandler::new(SubstreamProtocol::new(RPCProtocol), Duration::from_secs(30)) RPCHandler::new(SubstreamProtocol::new(RPCProtocol), Duration::from_secs(30))
} }
} }
impl<TSubstream, E> ProtocolsHandler for RPCHandler<TSubstream, E> impl<TSubstream> ProtocolsHandler for RPCHandler<TSubstream>
where where
TSubstream: AsyncRead + AsyncWrite, TSubstream: AsyncRead + AsyncWrite,
E: EthSpec,
{ {
type InEvent = RPCEvent; type InEvent = RPCEvent;
type OutEvent = RPCEvent; type OutEvent = RPCEvent;

View File

@ -16,7 +16,6 @@ pub use protocol::{RPCError, RPCProtocol, RPCRequest};
use slog::o; use slog::o;
use std::marker::PhantomData; use std::marker::PhantomData;
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
use types::EthSpec;
pub(crate) mod codec; pub(crate) mod codec;
mod handler; mod handler;
@ -50,16 +49,16 @@ impl RPCEvent {
/// Implements the libp2p `NetworkBehaviour` trait and therefore manages network-level /// Implements the libp2p `NetworkBehaviour` trait and therefore manages network-level
/// logic. /// logic.
pub struct RPC<TSubstream, E: EthSpec> { pub struct RPC<TSubstream> {
/// Queue of events to processed. /// Queue of events to processed.
events: Vec<NetworkBehaviourAction<RPCEvent, RPCMessage>>, events: Vec<NetworkBehaviourAction<RPCEvent, RPCMessage>>,
/// Pins the generic substream. /// Pins the generic substream.
marker: PhantomData<(TSubstream, E)>, marker: PhantomData<(TSubstream)>,
/// Slog logger for RPC behaviour. /// Slog logger for RPC behaviour.
_log: slog::Logger, _log: slog::Logger,
} }
impl<TSubstream, E: EthSpec> RPC<TSubstream, E> { impl<TSubstream> RPC<TSubstream> {
pub fn new(log: &slog::Logger) -> Self { pub fn new(log: &slog::Logger) -> Self {
let log = log.new(o!("Service" => "Libp2p-RPC")); let log = log.new(o!("Service" => "Libp2p-RPC"));
RPC { RPC {
@ -80,12 +79,11 @@ impl<TSubstream, E: EthSpec> RPC<TSubstream, E> {
} }
} }
impl<TSubstream, E> NetworkBehaviour for RPC<TSubstream, E> impl<TSubstream> NetworkBehaviour for RPC<TSubstream>
where where
TSubstream: AsyncRead + AsyncWrite, TSubstream: AsyncRead + AsyncWrite,
E: EthSpec,
{ {
type ProtocolsHandler = RPCHandler<TSubstream, E>; type ProtocolsHandler = RPCHandler<TSubstream>;
type OutEvent = RPCMessage; type OutEvent = RPCMessage;
fn new_handler(&mut self) -> Self::ProtocolsHandler { fn new_handler(&mut self) -> Self::ProtocolsHandler {

View File

@ -4,7 +4,7 @@ use crate::multiaddr::Protocol;
use crate::rpc::RPCEvent; use crate::rpc::RPCEvent;
use crate::NetworkConfig; use crate::NetworkConfig;
use crate::{Topic, TopicHash}; use crate::{Topic, TopicHash};
use crate::{BEACON_ATTESTATION_TOPIC, BEACON_PUBSUB_TOPIC}; use crate::{BEACON_ATTESTATION_TOPIC, BEACON_BLOCK_TOPIC};
use futures::prelude::*; use futures::prelude::*;
use futures::Stream; use futures::Stream;
use libp2p::core::{ use libp2p::core::{
@ -21,25 +21,24 @@ use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use std::time::Duration; use std::time::Duration;
use types::EthSpec;
type Libp2pStream = Boxed<(PeerId, StreamMuxerBox), Error>; type Libp2pStream = Boxed<(PeerId, StreamMuxerBox), Error>;
type Libp2pBehaviour<E> = Behaviour<Substream<StreamMuxerBox>, E>; type Libp2pBehaviour = Behaviour<Substream<StreamMuxerBox>>;
const NETWORK_KEY_FILENAME: &str = "key"; const NETWORK_KEY_FILENAME: &str = "key";
/// The configuration and state of the libp2p components for the beacon node. /// The configuration and state of the libp2p components for the beacon node.
pub struct Service<E: EthSpec> { pub struct Service {
/// The libp2p Swarm handler. /// The libp2p Swarm handler.
//TODO: Make this private //TODO: Make this private
pub swarm: Swarm<Libp2pStream, Libp2pBehaviour<E>>, pub swarm: Swarm<Libp2pStream, Libp2pBehaviour>,
/// This node's PeerId. /// This node's PeerId.
_local_peer_id: PeerId, _local_peer_id: PeerId,
/// The libp2p logger handle. /// The libp2p logger handle.
pub log: slog::Logger, pub log: slog::Logger,
} }
impl<E: EthSpec> Service<E> { impl Service {
pub fn new(config: NetworkConfig, log: slog::Logger) -> error::Result<Self> { pub fn new(config: NetworkConfig, log: slog::Logger) -> error::Result<Self> {
debug!(log, "Network-libp2p Service starting"); debug!(log, "Network-libp2p Service starting");
@ -92,7 +91,7 @@ impl<E: EthSpec> Service<E> {
//TODO: Handle multiple shard attestations. For now we simply use a separate topic for //TODO: Handle multiple shard attestations. For now we simply use a separate topic for
// attestations // attestations
topics.push(Topic::new(BEACON_ATTESTATION_TOPIC.into())); topics.push(Topic::new(BEACON_ATTESTATION_TOPIC.into()));
topics.push(Topic::new(BEACON_PUBSUB_TOPIC.into())); topics.push(Topic::new(BEACON_BLOCK_TOPIC.into()));
topics.append( topics.append(
&mut config &mut config
.topics .topics
@ -121,8 +120,8 @@ impl<E: EthSpec> Service<E> {
} }
} }
impl<E: EthSpec> Stream for Service<E> { impl Stream for Service {
type Item = Libp2pEvent<E>; type Item = Libp2pEvent;
type Error = crate::error::Error; type Error = crate::error::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
@ -136,7 +135,7 @@ impl<E: EthSpec> Stream for Service<E> {
topics, topics,
message, message,
} => { } => {
trace!(self.log, "Pubsub message received: {:?}", message); trace!(self.log, "Gossipsub message received"; "Message" => format!("{:?}", message));
return Ok(Async::Ready(Some(Libp2pEvent::PubsubMessage { return Ok(Async::Ready(Some(Libp2pEvent::PubsubMessage {
source, source,
topics, topics,
@ -196,7 +195,7 @@ fn build_transport(local_private_key: Keypair) -> Boxed<(PeerId, StreamMuxerBox)
} }
/// Events that can be obtained from polling the Libp2p Service. /// Events that can be obtained from polling the Libp2p Service.
pub enum Libp2pEvent<E: EthSpec> { pub enum Libp2pEvent {
/// An RPC response request has been received on the swarm. /// An RPC response request has been received on the swarm.
RPC(PeerId, RPCEvent), RPC(PeerId, RPCEvent),
/// Initiated the connection to a new peer. /// Initiated the connection to a new peer.
@ -207,7 +206,7 @@ pub enum Libp2pEvent<E: EthSpec> {
PubsubMessage { PubsubMessage {
source: PeerId, source: PeerId,
topics: Vec<TopicHash>, topics: Vec<TopicHash>,
message: Box<PubsubMessage<E>>, message: PubsubMessage,
}, },
} }

View File

@ -76,7 +76,7 @@ pub fn create_iron_http_server<T: BeaconChainTypes + 'static>(
pub fn start_service<T: BeaconChainTypes + 'static>( pub fn start_service<T: BeaconChainTypes + 'static>(
config: &HttpServerConfig, config: &HttpServerConfig,
executor: &TaskExecutor, executor: &TaskExecutor,
_network_chan: mpsc::UnboundedSender<NetworkMessage<T::EthSpec>>, _network_chan: mpsc::UnboundedSender<NetworkMessage>,
beacon_chain: Arc<BeaconChain<T>>, beacon_chain: Arc<BeaconChain<T>>,
db_path: PathBuf, db_path: PathBuf,
metrics_registry: Registry, metrics_registry: Registry,

View File

@ -14,7 +14,7 @@ use slog::{debug, warn};
use ssz::{Decode, DecodeError}; use ssz::{Decode, DecodeError};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use types::{BeaconBlockHeader, EthSpec}; use types::{Attestation, BeaconBlock, BeaconBlockHeader};
/// Handles messages received from the network and client and organises syncing. /// Handles messages received from the network and client and organises syncing.
pub struct MessageHandler<T: BeaconChainTypes> { pub struct MessageHandler<T: BeaconChainTypes> {
@ -23,14 +23,14 @@ pub struct MessageHandler<T: BeaconChainTypes> {
/// The syncing framework. /// The syncing framework.
sync: SimpleSync<T>, sync: SimpleSync<T>,
/// The context required to send messages to, and process messages from peers. /// The context required to send messages to, and process messages from peers.
network_context: NetworkContext<T::EthSpec>, network_context: NetworkContext,
/// The `MessageHandler` logger. /// The `MessageHandler` logger.
log: slog::Logger, log: slog::Logger,
} }
/// Types of messages the handler can receive. /// Types of messages the handler can receive.
#[derive(Debug)] #[derive(Debug)]
pub enum HandlerMessage<E: EthSpec> { pub enum HandlerMessage {
/// We have initiated a connection to a new peer. /// We have initiated a connection to a new peer.
PeerDialed(PeerId), PeerDialed(PeerId),
/// Peer has disconnected, /// Peer has disconnected,
@ -38,17 +38,17 @@ pub enum HandlerMessage<E: EthSpec> {
/// An RPC response/request has been received. /// An RPC response/request has been received.
RPC(PeerId, RPCEvent), RPC(PeerId, RPCEvent),
/// A gossip message has been received. /// A gossip message has been received.
PubsubMessage(PeerId, Box<PubsubMessage<E>>), PubsubMessage(PeerId, PubsubMessage),
} }
impl<T: BeaconChainTypes + 'static> MessageHandler<T> { impl<T: BeaconChainTypes + 'static> MessageHandler<T> {
/// Initializes and runs the MessageHandler. /// Initializes and runs the MessageHandler.
pub fn spawn( pub fn spawn(
beacon_chain: Arc<BeaconChain<T>>, beacon_chain: Arc<BeaconChain<T>>,
network_send: mpsc::UnboundedSender<NetworkMessage<T::EthSpec>>, network_send: mpsc::UnboundedSender<NetworkMessage>,
executor: &tokio::runtime::TaskExecutor, executor: &tokio::runtime::TaskExecutor,
log: slog::Logger, log: slog::Logger,
) -> error::Result<mpsc::UnboundedSender<HandlerMessage<T::EthSpec>>> { ) -> error::Result<mpsc::UnboundedSender<HandlerMessage>> {
debug!(log, "Service starting"); debug!(log, "Service starting");
let (handler_send, handler_recv) = mpsc::unbounded_channel(); let (handler_send, handler_recv) = mpsc::unbounded_channel();
@ -78,7 +78,7 @@ impl<T: BeaconChainTypes + 'static> MessageHandler<T> {
} }
/// Handle all messages incoming from the network service. /// Handle all messages incoming from the network service.
fn handle_message(&mut self, message: HandlerMessage<T::EthSpec>) { fn handle_message(&mut self, message: HandlerMessage) {
match message { match message {
// we have initiated a connection to a peer // we have initiated a connection to a peer
HandlerMessage::PeerDialed(peer_id) => { HandlerMessage::PeerDialed(peer_id) => {
@ -94,7 +94,7 @@ impl<T: BeaconChainTypes + 'static> MessageHandler<T> {
} }
// we have received an RPC message request/response // we have received an RPC message request/response
HandlerMessage::PubsubMessage(peer_id, gossip) => { HandlerMessage::PubsubMessage(peer_id, gossip) => {
self.handle_gossip(peer_id, *gossip); self.handle_gossip(peer_id, gossip);
} }
} }
} }
@ -218,6 +218,62 @@ impl<T: BeaconChainTypes + 'static> MessageHandler<T> {
} }
} }
/// Handle various RPC errors
fn handle_rpc_error(&mut self, peer_id: PeerId, request_id: RequestId, error: RPCError) {
//TODO: Handle error correctly
warn!(self.log, "RPC Error"; "Peer" => format!("{:?}", peer_id), "Request Id" => format!("{}", request_id), "Error" => format!("{:?}", error));
}
/// Handle RPC messages
fn handle_gossip(&mut self, peer_id: PeerId, gossip_message: PubsubMessage) {
match gossip_message {
PubsubMessage::Block(message) => match self.decode_gossip_block(message) {
Err(e) => {
debug!(self.log, "Invalid Gossiped Beacon Block"; "Peer" => format!("{}", peer_id), "Error" => format!("{:?}", e));
}
Ok(block) => {
let _should_forward_on =
self.sync
.on_block_gossip(peer_id, block, &mut self.network_context);
}
},
PubsubMessage::Attestation(message) => match self.decode_gossip_attestation(message) {
Err(e) => {
debug!(self.log, "Invalid Gossiped Attestation"; "Peer" => format!("{}", peer_id), "Error" => format!("{:?}", e));
}
Ok(attestation) => {
self.sync
.on_attestation_gossip(peer_id, attestation, &mut self.network_context)
}
},
PubsubMessage::Unknown(message) => {
// Received a message from an unknown topic. Ignore for now
debug!(self.log, "Unknown Gossip Message"; "Peer" => format!("{}", peer_id), "Message" => format!("{:?}", message));
}
}
}
/* Decoding of blocks and attestations from the network.
*
* TODO: Apply efficient decoding/verification of these objects
*/
fn decode_gossip_block(
&self,
beacon_block: Vec<u8>,
) -> Result<BeaconBlock<T::EthSpec>, DecodeError> {
//TODO: Apply verification before decoding.
BeaconBlock::from_ssz_bytes(&beacon_block)
}
fn decode_gossip_attestation(
&self,
beacon_block: Vec<u8>,
) -> Result<Attestation<T::EthSpec>, DecodeError> {
//TODO: Apply verification before decoding.
Attestation::from_ssz_bytes(&beacon_block)
}
/// Verifies and decodes the ssz-encoded block bodies received from peers. /// Verifies and decodes the ssz-encoded block bodies received from peers.
fn decode_block_bodies( fn decode_block_bodies(
&self, &self,
@ -241,39 +297,18 @@ impl<T: BeaconChainTypes + 'static> MessageHandler<T> {
//TODO: Implement faster header verification before decoding entirely //TODO: Implement faster header verification before decoding entirely
Vec::from_ssz_bytes(&headers_response.headers) Vec::from_ssz_bytes(&headers_response.headers)
} }
/// Handle various RPC errors
fn handle_rpc_error(&mut self, peer_id: PeerId, request_id: RequestId, error: RPCError) {
//TODO: Handle error correctly
warn!(self.log, "RPC Error"; "Peer" => format!("{:?}", peer_id), "Request Id" => format!("{}", request_id), "Error" => format!("{:?}", error));
}
/// Handle RPC messages
fn handle_gossip(&mut self, peer_id: PeerId, gossip_message: PubsubMessage<T::EthSpec>) {
match gossip_message {
PubsubMessage::Block(message) => {
let _should_forward_on =
self.sync
.on_block_gossip(peer_id, message, &mut self.network_context);
}
PubsubMessage::Attestation(message) => {
self.sync
.on_attestation_gossip(peer_id, message, &mut self.network_context)
}
}
}
} }
// TODO: RPC Rewrite makes this struct fairly pointless // TODO: RPC Rewrite makes this struct fairly pointless
pub struct NetworkContext<E: EthSpec> { pub struct NetworkContext {
/// The network channel to relay messages to the Network service. /// The network channel to relay messages to the Network service.
network_send: mpsc::UnboundedSender<NetworkMessage<E>>, network_send: mpsc::UnboundedSender<NetworkMessage>,
/// The `MessageHandler` logger. /// The `MessageHandler` logger.
log: slog::Logger, log: slog::Logger,
} }
impl<E: EthSpec> NetworkContext<E> { impl NetworkContext {
pub fn new(network_send: mpsc::UnboundedSender<NetworkMessage<E>>, log: slog::Logger) -> Self { pub fn new(network_send: mpsc::UnboundedSender<NetworkMessage>, log: slog::Logger) -> Self {
Self { network_send, log } Self { network_send, log }
} }

View File

@ -14,13 +14,12 @@ use slog::{debug, info, o, trace};
use std::sync::Arc; use std::sync::Arc;
use tokio::runtime::TaskExecutor; use tokio::runtime::TaskExecutor;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use types::EthSpec;
/// Service that handles communication between internal services and the eth2_libp2p network service. /// Service that handles communication between internal services and the eth2_libp2p network service.
pub struct Service<T: BeaconChainTypes> { pub struct Service<T: BeaconChainTypes> {
libp2p_service: Arc<Mutex<LibP2PService<T::EthSpec>>>, libp2p_service: Arc<Mutex<LibP2PService>>,
_libp2p_exit: oneshot::Sender<()>, _libp2p_exit: oneshot::Sender<()>,
_network_send: mpsc::UnboundedSender<NetworkMessage<T::EthSpec>>, _network_send: mpsc::UnboundedSender<NetworkMessage>,
_phantom: PhantomData<T>, //message_handler: MessageHandler, _phantom: PhantomData<T>, //message_handler: MessageHandler,
//message_handler_send: Sender<HandlerMessage> //message_handler_send: Sender<HandlerMessage>
} }
@ -31,9 +30,9 @@ impl<T: BeaconChainTypes + 'static> Service<T> {
config: &NetworkConfig, config: &NetworkConfig,
executor: &TaskExecutor, executor: &TaskExecutor,
log: slog::Logger, log: slog::Logger,
) -> error::Result<(Arc<Self>, mpsc::UnboundedSender<NetworkMessage<T::EthSpec>>)> { ) -> error::Result<(Arc<Self>, mpsc::UnboundedSender<NetworkMessage>)> {
// build the network channel // build the network channel
let (network_send, network_recv) = mpsc::unbounded_channel::<NetworkMessage<_>>(); let (network_send, network_recv) = mpsc::unbounded_channel::<NetworkMessage>();
// launch message handler thread // launch message handler thread
let message_handler_log = log.new(o!("Service" => "MessageHandler")); let message_handler_log = log.new(o!("Service" => "MessageHandler"));
let message_handler_send = MessageHandler::spawn( let message_handler_send = MessageHandler::spawn(
@ -65,15 +64,15 @@ impl<T: BeaconChainTypes + 'static> Service<T> {
Ok((Arc::new(network_service), network_send)) Ok((Arc::new(network_service), network_send))
} }
pub fn libp2p_service(&self) -> Arc<Mutex<LibP2PService<T::EthSpec>>> { pub fn libp2p_service(&self) -> Arc<Mutex<LibP2PService>> {
self.libp2p_service.clone() self.libp2p_service.clone()
} }
} }
fn spawn_service<E: EthSpec>( fn spawn_service(
libp2p_service: Arc<Mutex<LibP2PService<E>>>, libp2p_service: Arc<Mutex<LibP2PService>>,
network_recv: mpsc::UnboundedReceiver<NetworkMessage<E>>, network_recv: mpsc::UnboundedReceiver<NetworkMessage>,
message_handler_send: mpsc::UnboundedSender<HandlerMessage<E>>, message_handler_send: mpsc::UnboundedSender<HandlerMessage>,
executor: &TaskExecutor, executor: &TaskExecutor,
log: slog::Logger, log: slog::Logger,
) -> error::Result<tokio::sync::oneshot::Sender<()>> { ) -> error::Result<tokio::sync::oneshot::Sender<()>> {
@ -99,10 +98,10 @@ fn spawn_service<E: EthSpec>(
} }
//TODO: Potentially handle channel errors //TODO: Potentially handle channel errors
fn network_service<E: EthSpec>( fn network_service(
libp2p_service: Arc<Mutex<LibP2PService<E>>>, libp2p_service: Arc<Mutex<LibP2PService>>,
mut network_recv: mpsc::UnboundedReceiver<NetworkMessage<E>>, mut network_recv: mpsc::UnboundedReceiver<NetworkMessage>,
mut message_handler_send: mpsc::UnboundedSender<HandlerMessage<E>>, mut message_handler_send: mpsc::UnboundedSender<HandlerMessage>,
log: slog::Logger, log: slog::Logger,
) -> impl futures::Future<Item = (), Error = eth2_libp2p::error::Error> { ) -> impl futures::Future<Item = (), Error = eth2_libp2p::error::Error> {
futures::future::poll_fn(move || -> Result<_, eth2_libp2p::error::Error> { futures::future::poll_fn(move || -> Result<_, eth2_libp2p::error::Error> {
@ -119,7 +118,7 @@ fn network_service<E: EthSpec>(
}, },
NetworkMessage::Publish { topics, message } => { NetworkMessage::Publish { topics, message } => {
debug!(log, "Sending pubsub message"; "topics" => format!("{:?}",topics)); debug!(log, "Sending pubsub message"; "topics" => format!("{:?}",topics));
libp2p_service.lock().swarm.publish(topics, *message); libp2p_service.lock().swarm.publish(topics, message);
} }
}, },
Ok(Async::NotReady) => break, Ok(Async::NotReady) => break,
@ -176,14 +175,14 @@ fn network_service<E: EthSpec>(
/// Types of messages that the network service can receive. /// Types of messages that the network service can receive.
#[derive(Debug)] #[derive(Debug)]
pub enum NetworkMessage<E: EthSpec> { pub enum NetworkMessage {
/// Send a message to libp2p service. /// Send a message to libp2p service.
//TODO: Define typing for messages across the wire //TODO: Define typing for messages across the wire
Send(PeerId, OutgoingMessage), Send(PeerId, OutgoingMessage),
/// Publish a message to pubsub mechanism. /// Publish a message to pubsub mechanism.
Publish { Publish {
topics: Vec<Topic>, topics: Vec<Topic>,
message: Box<PubsubMessage<E>>, message: PubsubMessage,
}, },
} }

View File

@ -123,7 +123,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
/// Handle the connection of a new peer. /// Handle the connection of a new peer.
/// ///
/// Sends a `Hello` message to the peer. /// Sends a `Hello` message to the peer.
pub fn on_connect(&self, peer_id: PeerId, network: &mut NetworkContext<T::EthSpec>) { pub fn on_connect(&self, peer_id: PeerId, network: &mut NetworkContext) {
info!(self.log, "PeerConnected"; "peer" => format!("{:?}", peer_id)); info!(self.log, "PeerConnected"; "peer" => format!("{:?}", peer_id));
network.send_rpc_request(peer_id, RPCRequest::Hello(hello_message(&self.chain))); network.send_rpc_request(peer_id, RPCRequest::Hello(hello_message(&self.chain)));
@ -137,7 +137,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
peer_id: PeerId, peer_id: PeerId,
request_id: RequestId, request_id: RequestId,
hello: HelloMessage, hello: HelloMessage,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!(self.log, "HelloRequest"; "peer" => format!("{:?}", peer_id)); debug!(self.log, "HelloRequest"; "peer" => format!("{:?}", peer_id));
@ -156,7 +156,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
hello: HelloMessage, hello: HelloMessage,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!(self.log, "HelloResponse"; "peer" => format!("{:?}", peer_id)); debug!(self.log, "HelloResponse"; "peer" => format!("{:?}", peer_id));
@ -171,7 +171,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
hello: HelloMessage, hello: HelloMessage,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
let remote = PeerSyncInfo::from(hello); let remote = PeerSyncInfo::from(hello);
let local = PeerSyncInfo::from(&self.chain); let local = PeerSyncInfo::from(&self.chain);
@ -278,7 +278,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
peer_id: PeerId, peer_id: PeerId,
request_id: RequestId, request_id: RequestId,
req: BeaconBlockRootsRequest, req: BeaconBlockRootsRequest,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!( debug!(
self.log, self.log,
@ -323,7 +323,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
res: BeaconBlockRootsResponse, res: BeaconBlockRootsResponse,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!( debug!(
self.log, self.log,
@ -387,7 +387,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
peer_id: PeerId, peer_id: PeerId,
request_id: RequestId, request_id: RequestId,
req: BeaconBlockHeadersRequest, req: BeaconBlockHeadersRequest,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!( debug!(
self.log, self.log,
@ -440,7 +440,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
headers: Vec<BeaconBlockHeader>, headers: Vec<BeaconBlockHeader>,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!( debug!(
self.log, self.log,
@ -472,7 +472,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
peer_id: PeerId, peer_id: PeerId,
request_id: RequestId, request_id: RequestId,
req: BeaconBlockBodiesRequest, req: BeaconBlockBodiesRequest,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
let block_bodies: Vec<BeaconBlockBody<_>> = req let block_bodies: Vec<BeaconBlockBody<_>> = req
.block_roots .block_roots
@ -518,7 +518,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
res: DecodedBeaconBlockBodiesResponse<T::EthSpec>, res: DecodedBeaconBlockBodiesResponse<T::EthSpec>,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!( debug!(
self.log, self.log,
@ -557,7 +557,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
block: BeaconBlock<T::EthSpec>, block: BeaconBlock<T::EthSpec>,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) -> bool { ) -> bool {
if let Some(outcome) = if let Some(outcome) =
self.process_block(peer_id.clone(), block.clone(), network, &"gossip") self.process_block(peer_id.clone(), block.clone(), network, &"gossip")
@ -627,7 +627,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
_peer_id: PeerId, _peer_id: PeerId,
msg: Attestation<T::EthSpec>, msg: Attestation<T::EthSpec>,
_network: &mut NetworkContext<T::EthSpec>, _network: &mut NetworkContext,
) { ) {
match self.chain.process_attestation(msg) { match self.chain.process_attestation(msg) {
Ok(()) => info!(self.log, "ImportedAttestation"; "source" => "gossip"), Ok(()) => info!(self.log, "ImportedAttestation"; "source" => "gossip"),
@ -642,7 +642,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
req: BeaconBlockRootsRequest, req: BeaconBlockRootsRequest,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
// Potentially set state to sync. // Potentially set state to sync.
if self.state == SyncState::Idle && req.count > SLOT_IMPORT_TOLERANCE { if self.state == SyncState::Idle && req.count > SLOT_IMPORT_TOLERANCE {
@ -666,7 +666,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
req: BeaconBlockHeadersRequest, req: BeaconBlockHeadersRequest,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!( debug!(
self.log, self.log,
@ -683,7 +683,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
req: BeaconBlockBodiesRequest, req: BeaconBlockBodiesRequest,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
) { ) {
debug!( debug!(
self.log, self.log,
@ -719,7 +719,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
block_root: Hash256, block_root: Hash256,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
source: &str, source: &str,
) -> Option<BlockProcessingOutcome> { ) -> Option<BlockProcessingOutcome> {
match self.import_queue.attempt_complete_block(block_root) { match self.import_queue.attempt_complete_block(block_root) {
@ -812,7 +812,7 @@ impl<T: BeaconChainTypes> SimpleSync<T> {
&mut self, &mut self,
peer_id: PeerId, peer_id: PeerId,
block: BeaconBlock<T::EthSpec>, block: BeaconBlock<T::EthSpec>,
network: &mut NetworkContext<T::EthSpec>, network: &mut NetworkContext,
source: &str, source: &str,
) -> Option<BlockProcessingOutcome> { ) -> Option<BlockProcessingOutcome> {
let processing_result = self.chain.process_block(block.clone()); let processing_result = self.chain.process_block(block.clone());
@ -917,8 +917,8 @@ fn hello_message<T: BeaconChainTypes>(beacon_chain: &BeaconChain<T>) -> HelloMes
network_id: spec.network_id, network_id: spec.network_id,
//TODO: Correctly define the chain id //TODO: Correctly define the chain id
chain_id: spec.network_id as u64, chain_id: spec.network_id as u64,
latest_finalized_root: state.finalized_root, latest_finalized_root: state.finalized_checkpoint.root,
latest_finalized_epoch: state.finalized_epoch, latest_finalized_epoch: state.finalized_checkpoint.epoch,
best_root: beacon_chain.head().beacon_block_root, best_root: beacon_chain.head().beacon_block_root,
best_slot: state.slot, best_slot: state.slot,
} }

View File

@ -11,7 +11,7 @@ use protos::services::{
}; };
use protos::services_grpc::AttestationService; use protos::services_grpc::AttestationService;
use slog::{error, info, trace, warn}; use slog::{error, info, trace, warn};
use ssz::{ssz_encode, Decode}; use ssz::{ssz_encode, Decode, Encode};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use types::Attestation; use types::Attestation;
@ -19,7 +19,7 @@ use types::Attestation;
#[derive(Clone)] #[derive(Clone)]
pub struct AttestationServiceInstance<T: BeaconChainTypes> { pub struct AttestationServiceInstance<T: BeaconChainTypes> {
pub chain: Arc<BeaconChain<T>>, pub chain: Arc<BeaconChain<T>>,
pub network_chan: mpsc::UnboundedSender<NetworkMessage<T::EthSpec>>, pub network_chan: mpsc::UnboundedSender<NetworkMessage>,
pub log: slog::Logger, pub log: slog::Logger,
} }
@ -141,12 +141,12 @@ impl<T: BeaconChainTypes> AttestationService for AttestationServiceInstance<T> {
// valid attestation, propagate to the network // valid attestation, propagate to the network
let topic = Topic::new(BEACON_ATTESTATION_TOPIC.into()); let topic = Topic::new(BEACON_ATTESTATION_TOPIC.into());
let message = PubsubMessage::Attestation(attestation); let message = PubsubMessage::Attestation(attestation.as_ssz_bytes());
self.network_chan self.network_chan
.try_send(NetworkMessage::Publish { .try_send(NetworkMessage::Publish {
topics: vec![topic], topics: vec![topic],
message: Box::new(message), message: message,
}) })
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
error!( error!(

View File

@ -1,5 +1,5 @@
use beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome}; use beacon_chain::{BeaconChain, BeaconChainTypes, BlockProcessingOutcome};
use eth2_libp2p::BEACON_PUBSUB_TOPIC; use eth2_libp2p::BEACON_BLOCK_TOPIC;
use eth2_libp2p::{PubsubMessage, Topic}; use eth2_libp2p::{PubsubMessage, Topic};
use futures::Future; use futures::Future;
use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink}; use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
@ -11,7 +11,7 @@ use protos::services::{
use protos::services_grpc::BeaconBlockService; use protos::services_grpc::BeaconBlockService;
use slog::Logger; use slog::Logger;
use slog::{error, info, trace, warn}; use slog::{error, info, trace, warn};
use ssz::{ssz_encode, Decode}; use ssz::{ssz_encode, Decode, Encode};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use types::{BeaconBlock, Signature, Slot}; use types::{BeaconBlock, Signature, Slot};
@ -19,7 +19,7 @@ use types::{BeaconBlock, Signature, Slot};
#[derive(Clone)] #[derive(Clone)]
pub struct BeaconBlockServiceInstance<T: BeaconChainTypes> { pub struct BeaconBlockServiceInstance<T: BeaconChainTypes> {
pub chain: Arc<BeaconChain<T>>, pub chain: Arc<BeaconChain<T>>,
pub network_chan: mpsc::UnboundedSender<NetworkMessage<T::EthSpec>>, pub network_chan: mpsc::UnboundedSender<NetworkMessage>,
pub log: Logger, pub log: Logger,
} }
@ -106,14 +106,14 @@ impl<T: BeaconChainTypes> BeaconBlockService for BeaconBlockServiceInstance<T> {
); );
// get the network topic to send on // get the network topic to send on
let topic = Topic::new(BEACON_PUBSUB_TOPIC.into()); let topic = Topic::new(BEACON_BLOCK_TOPIC.into());
let message = PubsubMessage::Block(block); let message = PubsubMessage::Block(block.as_ssz_bytes());
// Publish the block to the p2p network via gossipsub. // Publish the block to the p2p network via gossipsub.
self.network_chan self.network_chan
.try_send(NetworkMessage::Publish { .try_send(NetworkMessage::Publish {
topics: vec![topic], topics: vec![topic],
message: Box::new(message), message: message,
}) })
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
error!( error!(

View File

@ -25,7 +25,7 @@ use tokio::sync::mpsc;
pub fn start_server<T: BeaconChainTypes + Clone + 'static>( pub fn start_server<T: BeaconChainTypes + Clone + 'static>(
config: &RPCConfig, config: &RPCConfig,
executor: &TaskExecutor, executor: &TaskExecutor,
network_chan: mpsc::UnboundedSender<NetworkMessage<T::EthSpec>>, network_chan: mpsc::UnboundedSender<NetworkMessage>,
beacon_chain: Arc<BeaconChain<T>>, beacon_chain: Arc<BeaconChain<T>>,
log: &slog::Logger, log: &slog::Logger,
) -> exit_future::Signal { ) -> exit_future::Signal {

View File

@ -207,12 +207,26 @@ pub struct InteropEthSpec;
impl EthSpec for InteropEthSpec { impl EthSpec for InteropEthSpec {
type ShardCount = U8; type ShardCount = U8;
type SlotsPerHistoricalRoot = U64;
type LatestRandaoMixesLength = U64;
type LatestActiveIndexRootsLength = U64;
type LatestSlashedExitLength = U64;
type SlotsPerEpoch = U8; type SlotsPerEpoch = U8;
type GenesisEpoch = U0; type SlotsPerHistoricalRoot = U64;
type SlotsPerEth1VotingPeriod = U16;
type EpochsPerHistoricalVector = U64;
type EpochsPerSlashingsVector = U64;
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
params_from_eth_spec!(MainnetEthSpec {
JustificationBitsLength,
MaxValidatorsPerCommittee,
GenesisEpoch,
HistoricalRootsLimit,
ValidatorRegistryLimit,
MaxProposerSlashings,
MaxAttesterSlashings,
MaxAttestations,
MaxDeposits,
MaxVoluntaryExits,
MaxTransfers
});
fn default_spec() -> ChainSpec { fn default_spec() -> ChainSpec {
ChainSpec::interop() ChainSpec::interop()

View File

@ -214,7 +214,7 @@ fn main() {
eth2_config, eth2_config,
log.clone(), log.clone(),
), ),
"interop" => ValidatorService::<ValidatorServiceClient, Keypair>::start::<InteropEthSpec>( "interop" => ValidatorService::<ValidatorServiceClient, Keypair, InteropEthSpec>::start(
client_config, client_config,
eth2_config, eth2_config,
log.clone(), log.clone(),