Merge pull request #322 from sigp/paul-sync

Syncing via Phase 0 Wire Protocol
This commit is contained in:
Age Manning
2019-03-28 17:33:53 +11:00
committed by GitHub
22 changed files with 2254 additions and 228 deletions

View File

@@ -1,6 +1,7 @@
use ssz::{Decodable, DecodeError, Encodable, SszStream};
/// Available RPC methods types and ids.
use ssz_derive::{Decode, Encode};
use types::{BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot};
use types::{Attestation, BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot};
#[derive(Debug)]
/// Available Serenity Libp2p RPC methods
@@ -53,13 +54,27 @@ impl Into<u16> for RPCMethod {
#[derive(Debug, Clone)]
pub enum RPCRequest {
Hello(HelloMessage),
Goodbye(u64),
Goodbye(GoodbyeReason),
BeaconBlockRoots(BeaconBlockRootsRequest),
BeaconBlockHeaders(BeaconBlockHeadersRequest),
BeaconBlockBodies(BeaconBlockBodiesRequest),
BeaconChainState(BeaconChainStateRequest),
}
impl RPCRequest {
pub fn method_id(&self) -> u16 {
let method = match self {
RPCRequest::Hello(_) => RPCMethod::Hello,
RPCRequest::Goodbye(_) => RPCMethod::Goodbye,
RPCRequest::BeaconBlockRoots(_) => RPCMethod::BeaconBlockRoots,
RPCRequest::BeaconBlockHeaders(_) => RPCMethod::BeaconBlockHeaders,
RPCRequest::BeaconBlockBodies(_) => RPCMethod::BeaconBlockBodies,
RPCRequest::BeaconChainState(_) => RPCMethod::BeaconChainState,
};
method.into()
}
}
#[derive(Debug, Clone)]
pub enum RPCResponse {
Hello(HelloMessage),
@@ -69,6 +84,19 @@ pub enum RPCResponse {
BeaconChainState(BeaconChainStateResponse),
}
impl RPCResponse {
pub fn method_id(&self) -> u16 {
let method = match self {
RPCResponse::Hello(_) => RPCMethod::Hello,
RPCResponse::BeaconBlockRoots(_) => RPCMethod::BeaconBlockRoots,
RPCResponse::BeaconBlockHeaders(_) => RPCMethod::BeaconBlockHeaders,
RPCResponse::BeaconBlockBodies(_) => RPCMethod::BeaconBlockBodies,
RPCResponse::BeaconChainState(_) => RPCMethod::BeaconChainState,
};
method.into()
}
}
/* Request/Response data structures for RPC methods */
/// The HELLO request/response handshake message.
@@ -86,76 +114,125 @@ pub struct HelloMessage {
pub best_slot: Slot,
}
/// The reason given for a `Goodbye` message.
///
/// Note: any unknown `u64::into(n)` will resolve to `GoodbyeReason::Unknown` for any unknown `n`,
/// however `GoodbyeReason::Unknown.into()` will go into `0_u64`. Therefore de-serializing then
/// re-serializing may not return the same bytes.
#[derive(Debug, Clone)]
pub enum GoodbyeReason {
ClientShutdown,
IrreleventNetwork,
Fault,
Unknown,
}
impl From<u64> for GoodbyeReason {
fn from(id: u64) -> GoodbyeReason {
match id {
1 => GoodbyeReason::ClientShutdown,
2 => GoodbyeReason::IrreleventNetwork,
3 => GoodbyeReason::Fault,
_ => GoodbyeReason::Unknown,
}
}
}
impl Into<u64> for GoodbyeReason {
fn into(self) -> u64 {
match self {
GoodbyeReason::Unknown => 0,
GoodbyeReason::ClientShutdown => 1,
GoodbyeReason::IrreleventNetwork => 2,
GoodbyeReason::Fault => 3,
}
}
}
impl Encodable for GoodbyeReason {
fn ssz_append(&self, s: &mut SszStream) {
let id: u64 = (*self).clone().into();
id.ssz_append(s);
}
}
impl Decodable for GoodbyeReason {
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), DecodeError> {
let (id, index) = u64::ssz_decode(bytes, index)?;
Ok((Self::from(id), index))
}
}
/// Request a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockRootsRequest {
/// The starting slot of the requested blocks.
start_slot: Slot,
pub start_slot: Slot,
/// The number of blocks from the start slot.
count: u64, // this must be less than 32768. //TODO: Enforce this in the lower layers
pub count: u64, // this must be less than 32768. //TODO: Enforce this in the lower layers
}
/// Response containing a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockRootsResponse {
/// List of requested blocks and associated slots.
roots: Vec<BlockRootSlot>,
pub roots: Vec<BlockRootSlot>,
}
/// Contains a block root and associated slot.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BlockRootSlot {
/// The block root.
block_root: Hash256,
pub block_root: Hash256,
/// The block slot.
slot: Slot,
pub slot: Slot,
}
/// Request a number of beacon block headers from a peer.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockHeadersRequest {
/// The starting header hash of the requested headers.
start_root: Hash256,
pub start_root: Hash256,
/// The starting slot of the requested headers.
start_slot: Slot,
pub start_slot: Slot,
/// The maximum number of headers than can be returned.
max_headers: u64,
pub max_headers: u64,
/// The maximum number of slots to skip between blocks.
skip_slots: u64,
pub skip_slots: u64,
}
/// Response containing requested block headers.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockHeadersResponse {
/// The list of requested beacon block headers.
headers: Vec<BeaconBlockHeader>,
pub headers: Vec<BeaconBlockHeader>,
}
/// Request a number of beacon block bodies from a peer.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockBodiesRequest {
/// The list of beacon block bodies being requested.
block_roots: Hash256,
pub block_roots: Vec<Hash256>,
}
/// Response containing the list of requested beacon block bodies.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockBodiesResponse {
/// The list of beacon block bodies being requested.
block_bodies: Vec<BeaconBlockBody>,
pub block_bodies: Vec<BeaconBlockBody>,
}
/// Request values for tree hashes which yield a blocks `state_root`.
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconChainStateRequest {
/// The tree hashes that a value is requested for.
hashes: Vec<Hash256>,
pub hashes: Vec<Hash256>,
}
/// Request values for tree hashes which yield a blocks `state_root`.
// Note: TBD
#[derive(Encode, Decode, Clone, Debug)]
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconChainStateResponse {
/// The values corresponding the to the requested tree hashes.
values: bool, //TBD - stubbed with encodeable bool
pub values: bool, //TBD - stubbed with encodeable bool
}

View File

@@ -2,7 +2,7 @@
///
/// This is purpose built for Ethereum 2.0 serenity and the protocol listens on
/// `/eth/serenity/rpc/1.0.0`
mod methods;
pub mod methods;
mod protocol;
use futures::prelude::*;
@@ -12,7 +12,7 @@ use libp2p::core::swarm::{
};
use libp2p::{Multiaddr, PeerId};
pub use methods::{HelloMessage, RPCMethod, RPCRequest, RPCResponse};
pub use protocol::{RPCEvent, RPCProtocol};
pub use protocol::{RPCEvent, RPCProtocol, RequestId};
use slog::o;
use std::marker::PhantomData;
use tokio::io::{AsyncRead, AsyncWrite};

View File

@@ -1,6 +1,7 @@
use super::methods::*;
use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo};
use ssz::{ssz_encode, Decodable, Encodable, SszStream};
use ssz::{ssz_encode, Decodable, DecodeError as SSZDecodeError, Encodable, SszStream};
use std::hash::{Hash, Hasher};
use std::io;
use std::iter;
use tokio::io::{AsyncRead, AsyncWrite};
@@ -29,16 +30,65 @@ impl Default for RPCProtocol {
}
}
/// A monotonic counter for ordering `RPCRequest`s.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct RequestId(u64);
impl RequestId {
/// Increment the request id.
pub fn increment(&mut self) {
self.0 += 1
}
/// Return the previous id.
pub fn previous(&self) -> Self {
Self(self.0 - 1)
}
}
impl Eq for RequestId {}
impl Hash for RequestId {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl From<u64> for RequestId {
fn from(x: u64) -> RequestId {
RequestId(x)
}
}
impl Into<u64> for RequestId {
fn into(self) -> u64 {
self.0
}
}
impl Encodable for RequestId {
fn ssz_append(&self, s: &mut SszStream) {
self.0.ssz_append(s);
}
}
impl Decodable for RequestId {
fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), SSZDecodeError> {
let (id, index) = u64::ssz_decode(bytes, index)?;
Ok((Self::from(id), index))
}
}
/// The RPC types which are sent/received in this protocol.
#[derive(Debug, Clone)]
pub enum RPCEvent {
Request {
id: u64,
id: RequestId,
method_id: u16,
body: RPCRequest,
},
Response {
id: u64,
id: RequestId,
method_id: u16, //TODO: Remove and process decoding upstream
result: RPCResponse,
},
@@ -75,7 +125,7 @@ fn decode(packet: Vec<u8>) -> Result<RPCEvent, DecodeError> {
// decode the header of the rpc
// request/response
let (request, index) = bool::ssz_decode(&packet, 0)?;
let (id, index) = u64::ssz_decode(&packet, index)?;
let (id, index) = RequestId::ssz_decode(&packet, index)?;
let (method_id, index) = u16::ssz_decode(&packet, index)?;
if request {
@@ -85,8 +135,8 @@ fn decode(packet: Vec<u8>) -> Result<RPCEvent, DecodeError> {
RPCRequest::Hello(hello_body)
}
RPCMethod::Goodbye => {
let (goodbye_code, _index) = u64::ssz_decode(&packet, index)?;
RPCRequest::Goodbye(goodbye_code)
let (goodbye_reason, _index) = GoodbyeReason::ssz_decode(&packet, index)?;
RPCRequest::Goodbye(goodbye_reason)
}
RPCMethod::BeaconBlockRoots => {
let (block_roots_request, _index) =