From dba54840736b7e65e4d1faa3dc47392966d1de81 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sun, 28 Apr 2019 20:02:04 -0400 Subject: [PATCH 01/15] Added messages in ETH2.0 wire protocol --- src/p2p/wire/messages.ts | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/p2p/wire/messages.ts diff --git a/src/p2p/wire/messages.ts b/src/p2p/wire/messages.ts new file mode 100644 index 000000000000..e0f7b9600945 --- /dev/null +++ b/src/p2p/wire/messages.ts @@ -0,0 +1,79 @@ + +export interface Request { + id: number; + method_id: number; + body: string; +} + +export interface Response { + id: number; + response_code: number; + result: Buffer; +} + +// Method ID: 0 + +export interface Hello { + network_id: number; + chain_id: number; + latest_finalized_root: Buffer; + latest_finalized_epoch: number; + best_root: Buffer; + best_slot: number; +} + +// Method ID: 1 + +export interface Goodbye { + reason: number; +} + +// Method ID: 2 + +export interface GetStatus { + sha: Buffer; + user_agent: Buffer; + timestamp: number; +} + +// Method ID: 10 + +export interface RequestBeaconBlockRoots { + start_slot: number; + count: number; +} + +export interface BeaconBlockRoots { + block_root: Buffer; + slot: number; + // Doesn't currently exist as a standalone type + roots: []BlockRootSlot; +} + +// Method ID: 11 +export interface RequestBeaconBlockHeader { + // Doesn't currently exist as a standalone type + start_root: HashTreeRoot; + start_slot: number; + max_headers: number; + skip_slots: number; +} + +export interface BeaconBlockHeaders { + // Doesn't currently exist as a standalone type + headers: []BeaconBlockHeader +} + +// Method ID: 12 +export interface RequestBeaconBlockBodies { + block_roots: []HashTreeRoot; +} + +export interface BeaconBlockBodies { + block_bodies: []BeaconBlockBody; +} + +// Method ID: 13 +export interface RequestBeaconChainState { + hashes: []HashTreeRoot; +} From 85654575f12c6e5cd055f9ad8950434fa3c22d57 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sun, 28 Apr 2019 20:02:04 -0400 Subject: [PATCH 02/15] Added messages in ETH2.0 wire protocol --- src/p2p/wire/messages.ts | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/p2p/wire/messages.ts diff --git a/src/p2p/wire/messages.ts b/src/p2p/wire/messages.ts new file mode 100644 index 000000000000..e0f7b9600945 --- /dev/null +++ b/src/p2p/wire/messages.ts @@ -0,0 +1,79 @@ + +export interface Request { + id: number; + method_id: number; + body: string; +} + +export interface Response { + id: number; + response_code: number; + result: Buffer; +} + +// Method ID: 0 + +export interface Hello { + network_id: number; + chain_id: number; + latest_finalized_root: Buffer; + latest_finalized_epoch: number; + best_root: Buffer; + best_slot: number; +} + +// Method ID: 1 + +export interface Goodbye { + reason: number; +} + +// Method ID: 2 + +export interface GetStatus { + sha: Buffer; + user_agent: Buffer; + timestamp: number; +} + +// Method ID: 10 + +export interface RequestBeaconBlockRoots { + start_slot: number; + count: number; +} + +export interface BeaconBlockRoots { + block_root: Buffer; + slot: number; + // Doesn't currently exist as a standalone type + roots: []BlockRootSlot; +} + +// Method ID: 11 +export interface RequestBeaconBlockHeader { + // Doesn't currently exist as a standalone type + start_root: HashTreeRoot; + start_slot: number; + max_headers: number; + skip_slots: number; +} + +export interface BeaconBlockHeaders { + // Doesn't currently exist as a standalone type + headers: []BeaconBlockHeader +} + +// Method ID: 12 +export interface RequestBeaconBlockBodies { + block_roots: []HashTreeRoot; +} + +export interface BeaconBlockBodies { + block_bodies: []BeaconBlockBody; +} + +// Method ID: 13 +export interface RequestBeaconChainState { + hashes: []HashTreeRoot; +} From 2da711217766d8448549db271a586fb676f69f3d Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sun, 28 Apr 2019 20:02:04 -0400 Subject: [PATCH 03/15] Added messages in ETH2.0 wire protocol --- src/p2p/wire/messages.ts | 79 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/p2p/wire/messages.ts diff --git a/src/p2p/wire/messages.ts b/src/p2p/wire/messages.ts new file mode 100644 index 000000000000..e0f7b9600945 --- /dev/null +++ b/src/p2p/wire/messages.ts @@ -0,0 +1,79 @@ + +export interface Request { + id: number; + method_id: number; + body: string; +} + +export interface Response { + id: number; + response_code: number; + result: Buffer; +} + +// Method ID: 0 + +export interface Hello { + network_id: number; + chain_id: number; + latest_finalized_root: Buffer; + latest_finalized_epoch: number; + best_root: Buffer; + best_slot: number; +} + +// Method ID: 1 + +export interface Goodbye { + reason: number; +} + +// Method ID: 2 + +export interface GetStatus { + sha: Buffer; + user_agent: Buffer; + timestamp: number; +} + +// Method ID: 10 + +export interface RequestBeaconBlockRoots { + start_slot: number; + count: number; +} + +export interface BeaconBlockRoots { + block_root: Buffer; + slot: number; + // Doesn't currently exist as a standalone type + roots: []BlockRootSlot; +} + +// Method ID: 11 +export interface RequestBeaconBlockHeader { + // Doesn't currently exist as a standalone type + start_root: HashTreeRoot; + start_slot: number; + max_headers: number; + skip_slots: number; +} + +export interface BeaconBlockHeaders { + // Doesn't currently exist as a standalone type + headers: []BeaconBlockHeader +} + +// Method ID: 12 +export interface RequestBeaconBlockBodies { + block_roots: []HashTreeRoot; +} + +export interface BeaconBlockBodies { + block_bodies: []BeaconBlockBody; +} + +// Method ID: 13 +export interface RequestBeaconChainState { + hashes: []HashTreeRoot; +} From 8698363e197780dd89d94e14999c3aa47abc434a Mon Sep 17 00:00:00 2001 From: Mikerah Date: Sun, 5 May 2019 23:06:43 -0400 Subject: [PATCH 04/15] Completed 2-way handshake --- package.json | 1 + src/p2p/index.ts | 51 +++++++++++++++++++++++++++++++++++++-- src/p2p/wire/interface.ts | 0 src/p2p/wire/types.ts | 10 ++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/p2p/wire/interface.ts create mode 100644 src/p2p/wire/types.ts diff --git a/package.json b/package.json index ea344d337a58..ef4952f88578 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "pouchdb-adapter-memory": "^7.0.0", "pouchdb-core": "^7.0.0", "promisify-es6": "^1.0.3", + "pull-stream": "^3.6.10", "winston": "^3.2.1", "ws": "^6.2.1" }, diff --git a/src/p2p/index.ts b/src/p2p/index.ts index d7d1318c3554..003bf831a9ba 100644 --- a/src/p2p/index.ts +++ b/src/p2p/index.ts @@ -4,9 +4,30 @@ import {LodestarNode} from "./node"; import logger, {AbstractLogger} from "../logger"; import {PeerInfo} from "peer-info"; import LibP2p from "libp2p"; +import {pull} from "pull-stream"; import {PeerBook} from "peer-book"; import {PeerId} from "peer-id"; import {promisify} from "promisify-es6"; +import { + Request, + Response, + Hello, + Goodbye, + GetStatus, + BeaconBlockRootsRequest, + BeaconBlockRootsResponse, + BeaconBlockHeadersRequest, + BeaconBlockHeadersResponse, + BeaconBlockBodiesRequest, + BeaconBlockBodiesResponse, + BeaconChainStateRequest, + BeaconChainStateResponse +} from "./wire/messages"; + +import { + BlockRootSlot, + HashTreeRoot +} from "../wire/types"; export interface P2pOptions { maxPeers: number; @@ -48,7 +69,7 @@ export class P2PNetwork extends EventEmitter implements Service { this.refreshInterval = this.options.refreshInterval; this.peerBook = this.options.peerBook; this.privateKey = this.options.privateKey; - this.bootnodes = this.options.bootnodes; + this.bootnodes = this.options.bootnodes || []; this.started = false; @@ -89,11 +110,37 @@ export class P2PNetwork extends EventEmitter implements Service { }); + // 2-way handshake + const protocol: string = "/eth/serenity/beacon/rpc/1"; + const helloMsg: Hello = { + + }; + this.node.handle((proto, conn) => { + pull( + pull.values([Buffer.from(JSON.stringify(helloMsg))]), + conn, + pull.collect((values) => { + // Peers' responses + + }) + ); + }); this.node.on('peer:connect', (peerInfo) => { try { this.log.info(`Peer connected: ${peerInfo}`); this.peerBook.put(peerInfo); - this.discoveredPeers.add(peerInfo); + this.discoveredPeers.add(peerInfo); + this.node.dialProtocol(peerInfo, protocol, (err, conn) => { + pull( + pull.values([Buffer.from(JSON.stringify(helloMsg))]), + conn, + pull.collect((values) => { + // Peers responses + + }) + ); + }) + } catch (err) { this.log.error(err); } diff --git a/src/p2p/wire/interface.ts b/src/p2p/wire/interface.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/p2p/wire/types.ts b/src/p2p/wire/types.ts new file mode 100644 index 000000000000..e6a0a0131032 --- /dev/null +++ b/src/p2p/wire/types.ts @@ -0,0 +1,10 @@ +import {Slot} from "../../types/primitive" + +export interface BlockRootSlot { + block_root: Buffer; + slot: Slot; +} + +export interface HashTreeRoot { + hash: Buffer; +} From 560d066c7002bb7c5870c5f1ae0df9eb789a798f Mon Sep 17 00:00:00 2001 From: Mikerah Date: Mon, 6 May 2019 23:02:29 -0400 Subject: [PATCH 05/15] Refactored wire protocol api into rpc module --- src/rpc/api/wire/index.ts | 7 +++ src/rpc/api/wire/interface.ts | 39 +++++++++++++++ src/rpc/api/wire/messages.ts | 89 +++++++++++++++++++++++++++++++++++ src/rpc/api/wire/types.ts | 10 ++++ src/rpc/api/wire/wire.ts | 0 5 files changed, 145 insertions(+) create mode 100644 src/rpc/api/wire/index.ts create mode 100644 src/rpc/api/wire/interface.ts create mode 100644 src/rpc/api/wire/messages.ts create mode 100644 src/rpc/api/wire/types.ts create mode 100644 src/rpc/api/wire/wire.ts diff --git a/src/rpc/api/wire/index.ts b/src/rpc/api/wire/index.ts new file mode 100644 index 000000000000..fcadf8d9121c --- /dev/null +++ b/src/rpc/api/wire/index.ts @@ -0,0 +1,7 @@ +import {WireProtocolApi} from "./wire"; +import {IWireProtocolApi} from "./interface"; + +export { + WireProtocolApi, + IWireProtocolApi +}; diff --git a/src/rpc/api/wire/interface.ts b/src/rpc/api/wire/interface.ts new file mode 100644 index 000000000000..a247e33aa184 --- /dev/null +++ b/src/rpc/api/wire/interface.ts @@ -0,0 +1,39 @@ +import {IApi} from "../interface"; +import { + BeaconBlock, + BeaconState, + bytes32, + Fork, + number64, + SyncingStatus +} from "../../../types"; + +import { + Request, + Response, + Hello, + Goodbye, + GetStatusRequest, + GetStatusResponse, + BeaconBlockRootsRequest, + BeaconBlockRootsResponse, + BeaconBlockHeaderRequest, + BeaconBlockHeaderResponse, + BeaconBlockBodiesRequest, + BeaconBlockBodiesResponse, + BeaconChainStateRequest, + BeaconChainStateResponse +} from "./messages"; + +import { + BlockRootSlot, + HashTreeRoot +} from "./types"; + +export interface IWireProtocolApi extends IApi { + + /** + * Returns metadata about the remote node. + */ + GetStatus(): Promise<> +} diff --git a/src/rpc/api/wire/messages.ts b/src/rpc/api/wire/messages.ts new file mode 100644 index 000000000000..703267401eb1 --- /dev/null +++ b/src/rpc/api/wire/messages.ts @@ -0,0 +1,89 @@ +import {Slot} from "../../types/primitive"; +import {BlockRootSlot, HashTreeRoot} from "./types"; + +type RPCMethod = Hello | Goodbye | GetStatus; + +export interface Request { + id: number; + method_id: number; + body: string; +} + +export interface Response { + id: number; + response_code: number; + result: Buffer; +} + +// Method ID: 0 + +export interface Hello { + network_id: number; + chain_id: number; + latest_finalized_root: Buffer; + latest_finalized_epoch: number; + best_root: Buffer; + best_slot: Slot; +} + +// Method ID: 1 + +export interface Goodbye { + reason: number; +} + +// Method ID: 2 + +export interface GetStatus { + sha: Buffer; + user_agent: Buffer; + timestamp: number; +} + +// Method ID: 10 + +export interface BeaconBlockRootsRequest { + start_slot: Slot; + count: number; +} + +export interface BeaconBlockRootsResponse { + block_root: Buffer; + slot: Slot; + // Doesn't currently exist as a standalone type + roots: []BlockRootSlot; +} + +// Method ID: 11 +export interface BeaconBlockHeadersRequest { + // Doesn't currently exist as a standalone type + start_root: HashTreeRoot; + start_slot: Slot; + max_headers: number; + skip_slots: number; +} + +export interface BeaconBlockHeadersResponse { + // Doesn't currently exist as a standalone type + headers: []BeaconBlockHeader +} + +// Method ID: 12 +export interface BeaconBlockBodiesRequest { + block_roots: []HashTreeRoot; +} + +export interface BeaconBlockBodiesResponse { + block_bodies: []BeaconBlockBody; +} + +// Method ID: 13 +export interface BeaconChainStateRequest { + hashes: []HashTreeRoot; +} + +// Method ID: 14 +// Not yet defined in the ETH2.0 Wire spec. +export interface BeaconChainStateResponse { + +} diff --git a/src/rpc/api/wire/types.ts b/src/rpc/api/wire/types.ts new file mode 100644 index 000000000000..e6a0a0131032 --- /dev/null +++ b/src/rpc/api/wire/types.ts @@ -0,0 +1,10 @@ +import {Slot} from "../../types/primitive" + +export interface BlockRootSlot { + block_root: Buffer; + slot: Slot; +} + +export interface HashTreeRoot { + hash: Buffer; +} diff --git a/src/rpc/api/wire/wire.ts b/src/rpc/api/wire/wire.ts new file mode 100644 index 000000000000..e69de29bb2d1 From 5abed1050dc30b37e52bb9dc4e21eee1739d6824 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Mon, 6 May 2019 23:38:06 -0400 Subject: [PATCH 06/15] Completed RPC methods interface for wire protocol --- src/rpc/api/wire/interface.ts | 26 +++++++++++++++++++++++--- src/rpc/api/wire/messages.ts | 4 ++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/rpc/api/wire/interface.ts b/src/rpc/api/wire/interface.ts index a247e33aa184..588247a6bdd8 100644 --- a/src/rpc/api/wire/interface.ts +++ b/src/rpc/api/wire/interface.ts @@ -13,8 +13,7 @@ import { Response, Hello, Goodbye, - GetStatusRequest, - GetStatusResponse, + GetStatus, BeaconBlockRootsRequest, BeaconBlockRootsResponse, BeaconBlockHeaderRequest, @@ -35,5 +34,26 @@ export interface IWireProtocolApi extends IApi { /** * Returns metadata about the remote node. */ - GetStatus(): Promise<> + GetStatus(): Promise; + + /** + * Returns list of block roots and slots from the peer + */ + RequestBeaconBlockRoots(request: BeaconBlockRootsRequest): Promise; + + /** + * Returns beacon block headers from peer + */ + RequestBeaconBlockHeaders(request: BeaconBlockHeadersRequest): Promise; + + /** + * Returns block bodies associated with block roots from a peer + */ + RequestBeaconBlockBodies(request: BeaconBlockBodiesRequest): Promise; + + /** + * Returns the hashes of merkle tree nodes from merkelizing the block's state root. + */ + RequestBeaconChainStateRequest(request: BeaconChainStateRequest): Promise; + } diff --git a/src/rpc/api/wire/messages.ts b/src/rpc/api/wire/messages.ts index 703267401eb1..e91e74abbfae 100644 --- a/src/rpc/api/wire/messages.ts +++ b/src/rpc/api/wire/messages.ts @@ -34,11 +34,11 @@ export interface Goodbye { // Method ID: 2 -export interface GetStatus { +export interface GetStatusRequest { sha: Buffer; user_agent: Buffer; timestamp: number; -} +} // Method ID: 10 From 07ea8874f849407a0edf66c5dd139da34db3c972 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Mon, 6 May 2019 23:54:49 -0400 Subject: [PATCH 07/15] Stubbed out wire.ts --- src/rpc/api/wire/interface.ts | 15 +-------- src/rpc/api/wire/wire.ts | 58 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/rpc/api/wire/interface.ts b/src/rpc/api/wire/interface.ts index 588247a6bdd8..a938a289bfb7 100644 --- a/src/rpc/api/wire/interface.ts +++ b/src/rpc/api/wire/interface.ts @@ -1,12 +1,4 @@ import {IApi} from "../interface"; -import { - BeaconBlock, - BeaconState, - bytes32, - Fork, - number64, - SyncingStatus -} from "../../../types"; import { Request, @@ -24,11 +16,6 @@ import { BeaconChainStateResponse } from "./messages"; -import { - BlockRootSlot, - HashTreeRoot -} from "./types"; - export interface IWireProtocolApi extends IApi { /** @@ -54,6 +41,6 @@ export interface IWireProtocolApi extends IApi { /** * Returns the hashes of merkle tree nodes from merkelizing the block's state root. */ - RequestBeaconChainStateRequest(request: BeaconChainStateRequest): Promise; + RequestBeaconChainState(request: BeaconChainStateRequest): Promise; } diff --git a/src/rpc/api/wire/wire.ts b/src/rpc/api/wire/wire.ts index e69de29bb2d1..a6d6ac4a3fe9 100644 --- a/src/rpc/api/wire/wire.ts +++ b/src/rpc/api/wire/wire.ts @@ -0,0 +1,58 @@ +import {IWireProtocolApi} from "./interface"; +import {BeaconChain} from "../../../chain"; +import {DB} from "../../../db"; + +import { + Request, + Response, + Hello, + Goodbye, + BeaconBlockRootsRequest, + BeaconBlockRootsResponse, + BeaconBlockHeaderRequest, + BeaconBlockHeaderResponse, + BeaconBlockBodiesRequest, + BeaconBlockBodiesResponse, + BeaconChainStateRequest, + BeaconChainStateResponse +} from "./messages"; + +import { + BlockRootSlot, + HashTreeRoot +} from "./types"; + +export class WireProtocolApi implements IWireProtocolApi { + + public namespace: string; + + private chain: BeaconChain; + private db: DB; + + public constructor(opts, {chain, db}) { + this.namespace = 'eth2-wire'; + this.db; + this.chain; + } + + public async GetStatus(): Promise { + + } + + public async RequestBeaconBlockRoots(request: BeaconBlockRootsRequest): Promise { + + } + + public async RequestBeaconBlockHeaders(request: BeaconBlockHeadersRequest): Promise { + + } + + public async RequestBeaconBlockBodies(request: BeaconBlockBodiesRequest): Promise { + + } + + public async RequestBeaconChainState(request: BeaconChainStateRequest): Promise { + + } + +} From bd6752c6bda2892634361d4b492593c33aeb36c5 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Mon, 6 May 2019 23:56:58 -0400 Subject: [PATCH 08/15] Forgot to change import statement to reflect refactor in p2p/index.ts --- src/p2p/index.ts | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/p2p/index.ts b/src/p2p/index.ts index 003bf831a9ba..2b4c9b91773d 100644 --- a/src/p2p/index.ts +++ b/src/p2p/index.ts @@ -8,26 +8,7 @@ import {pull} from "pull-stream"; import {PeerBook} from "peer-book"; import {PeerId} from "peer-id"; import {promisify} from "promisify-es6"; -import { - Request, - Response, - Hello, - Goodbye, - GetStatus, - BeaconBlockRootsRequest, - BeaconBlockRootsResponse, - BeaconBlockHeadersRequest, - BeaconBlockHeadersResponse, - BeaconBlockBodiesRequest, - BeaconBlockBodiesResponse, - BeaconChainStateRequest, - BeaconChainStateResponse -} from "./wire/messages"; - -import { - BlockRootSlot, - HashTreeRoot -} from "../wire/types"; +import {Hello, Goodbye} from "../rpc/api/wire/messages"; export interface P2pOptions { maxPeers: number; @@ -37,6 +18,10 @@ export interface P2pOptions { bootnodes: string[]; } +export interface ChainOptions { + +} + /** * The P2PNetwork service manages p2p connection/subscription objects */ @@ -115,7 +100,7 @@ export class P2PNetwork extends EventEmitter implements Service { const helloMsg: Hello = { }; - this.node.handle((proto, conn) => { + this.node.handle(protocol, (proto, conn) => { pull( pull.values([Buffer.from(JSON.stringify(helloMsg))]), conn, @@ -147,7 +132,8 @@ export class P2PNetwork extends EventEmitter implements Service { }); this.node.on('peer:disconnect', (peerInfo) => { - try { + try { + this.peerBook.remove(peerInfo); this.discoveredPeers.delete(peerInfo); } catch (err) { From e25b0338808ae56056c3d1530e62fa365c7e5c8e Mon Sep 17 00:00:00 2001 From: Mikerah Date: Tue, 7 May 2019 20:59:32 -0400 Subject: [PATCH 09/15] Added some of Marin's and Greg's suggestions --- src/rpc/api/wire/messages.ts | 22 ++++++++++++---------- src/rpc/api/wire/wire.ts | 36 ++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/rpc/api/wire/messages.ts b/src/rpc/api/wire/messages.ts index e91e74abbfae..6885be80d900 100644 --- a/src/rpc/api/wire/messages.ts +++ b/src/rpc/api/wire/messages.ts @@ -1,12 +1,14 @@ import {Slot} from "../../types/primitive"; import {BlockRootSlot, HashTreeRoot} from "./types"; -type RPCMethod = Hello | Goodbye | GetStatus; +interface RequestBody { + +} export interface Request { id: number; method_id: number; - body: string; + body: RequestBody; } export interface Response { @@ -17,7 +19,7 @@ export interface Response { // Method ID: 0 -export interface Hello { +export interface Hello extends RequestBody { network_id: number; chain_id: number; latest_finalized_root: Buffer; @@ -28,13 +30,13 @@ export interface Hello { // Method ID: 1 -export interface Goodbye { +export interface Goodbye extends RequestBody { reason: number; } // Method ID: 2 -export interface GetStatusRequest { +export interface GetStatus extends RequestBody { sha: Buffer; user_agent: Buffer; timestamp: number; @@ -42,7 +44,7 @@ export interface GetStatusRequest { // Method ID: 10 -export interface BeaconBlockRootsRequest { +export interface BeaconBlockRootsRequest extends RequestBody { start_slot: Slot; count: number; } @@ -55,7 +57,7 @@ export interface BeaconBlockRootsResponse { } // Method ID: 11 -export interface BeaconBlockHeadersRequest { +export interface BeaconBlockHeadersRequest extends RequestBody { // Doesn't currently exist as a standalone type start_root: HashTreeRoot; start_slot: Slot; @@ -69,16 +71,16 @@ export interface BeaconBlockHeadersResponse { } // Method ID: 12 -export interface BeaconBlockBodiesRequest { +export interface BeaconBlockBodiesRequest extends RequestBody { block_roots: []HashTreeRoot; -} +} export interface BeaconBlockBodiesResponse { block_bodies: []BeaconBlockBody; } // Method ID: 13 -export interface BeaconChainStateRequest { +export interface BeaconChainStateRequest extends RequestBody { hashes: []HashTreeRoot; } diff --git a/src/rpc/api/wire/wire.ts b/src/rpc/api/wire/wire.ts index a6d6ac4a3fe9..1a91a7296ecd 100644 --- a/src/rpc/api/wire/wire.ts +++ b/src/rpc/api/wire/wire.ts @@ -24,35 +24,35 @@ import { export class WireProtocolApi implements IWireProtocolApi { - public namespace: string; + public namespace: string; - private chain: BeaconChain; - private db: DB; + private chain: BeaconChain; + private db: DB; - public constructor(opts, {chain, db}) { - this.namespace = 'eth2-wire'; - this.db; - this.chain; - } + public constructor(opts, {chain, db}) { + this.namespace = 'wire'; + this.db; + this.chain; + } - public async GetStatus(): Promise { + public async GetStatus(): Promise { - } + } - public async RequestBeaconBlockRoots(request: BeaconBlockRootsRequest): Promise { + public async RequestBeaconBlockRoots(request: BeaconBlockRootsRequest): Promise { - } + } - public async RequestBeaconBlockHeaders(request: BeaconBlockHeadersRequest): Promise { + public async RequestBeaconBlockHeaders(request: BeaconBlockHeadersRequest): Promise { - } + } - public async RequestBeaconBlockBodies(request: BeaconBlockBodiesRequest): Promise { + public async RequestBeaconBlockBodies(request: BeaconBlockBodiesRequest): Promise { - } + } - public async RequestBeaconChainState(request: BeaconChainStateRequest): Promise { + public async RequestBeaconChainState(request: BeaconChainStateRequest): Promise { - } + } } From 72e2c06fb21087a6fd3dfc673c8b56cdfcfd7e26 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Tue, 7 May 2019 23:08:05 -0400 Subject: [PATCH 10/15] Fixed lint errors in p2p/index.ts and made changes to the constructor, along with other changes --- src/node/index.ts | 2 +- src/p2p/index.ts | 31 +++++++++------ src/p2p/wire/interface.ts | 0 src/p2p/wire/messages.ts | 79 --------------------------------------- src/p2p/wire/types.ts | 10 ----- 5 files changed, 21 insertions(+), 101 deletions(-) delete mode 100644 src/p2p/wire/interface.ts delete mode 100644 src/p2p/wire/messages.ts delete mode 100644 src/p2p/wire/types.ts diff --git a/src/node/index.ts b/src/node/index.ts index 5f5e58ba927a..d53ad6908aca 100644 --- a/src/node/index.ts +++ b/src/node/index.ts @@ -52,7 +52,7 @@ class BeaconNode { ); this.db = new LevelDB(this.conf.db); - this.network = new P2PNetwork(this.conf.network); + this.network = new P2PNetwork(this.conf.network, {chain, db}); this.eth1 = new EthersEth1Notifier( this.conf.eth1, { diff --git a/src/p2p/index.ts b/src/p2p/index.ts index 2b4c9b91773d..0845daa54675 100644 --- a/src/p2p/index.ts +++ b/src/p2p/index.ts @@ -9,6 +9,8 @@ import {PeerBook} from "peer-book"; import {PeerId} from "peer-id"; import {promisify} from "promisify-es6"; import {Hello, Goodbye} from "../rpc/api/wire/messages"; +import {DB} from "../db"; +import {BeaconChain} from "../chain" export interface P2pOptions { maxPeers: number; @@ -18,10 +20,6 @@ export interface P2pOptions { bootnodes: string[]; } -export interface ChainOptions { - -} - /** * The P2PNetwork service manages p2p connection/subscription objects */ @@ -47,7 +45,11 @@ export class P2PNetwork extends EventEmitter implements Service { private log: AbstractLogger; - public constructor(opts: P2pOptions) { + private chain: BeaconChain; + + private db: DB; + + public constructor(opts: P2pOptions, {chain, db}) { super(); this.options = opts; this.maxPeers = this.options.maxPeers; @@ -56,6 +58,8 @@ export class P2PNetwork extends EventEmitter implements Service { this.privateKey = this.options.privateKey; this.bootnodes = this.options.bootnodes || []; + this.chain = chain; + this.db = db; this.started = false; this.node = null; @@ -96,9 +100,15 @@ export class P2PNetwork extends EventEmitter implements Service { }); // 2-way handshake - const protocol: string = "/eth/serenity/beacon/rpc/1"; + const protocol = "/eth/serenity/beacon/rpc/1"; + // Placeholders to make this file compile temporarily const helloMsg: Hello = { - + networkId: 0, + chainId: 0, + latestFinalizedRoot: Buffer.from(""), + latestFinalizedEpoch: 0, + bestRoot: Buffer.from(""), + bestSlot: 0 }; this.node.handle(protocol, (proto, conn) => { pull( @@ -108,7 +118,7 @@ export class P2PNetwork extends EventEmitter implements Service { // Peers' responses }) - ); + ); }); this.node.on('peer:connect', (peerInfo) => { try { @@ -124,7 +134,7 @@ export class P2PNetwork extends EventEmitter implements Service { }) ); - }) + }); } catch (err) { this.log.error(err); @@ -132,8 +142,7 @@ export class P2PNetwork extends EventEmitter implements Service { }); this.node.on('peer:disconnect', (peerInfo) => { - try { - + try { this.peerBook.remove(peerInfo); this.discoveredPeers.delete(peerInfo); } catch (err) { diff --git a/src/p2p/wire/interface.ts b/src/p2p/wire/interface.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/p2p/wire/messages.ts b/src/p2p/wire/messages.ts deleted file mode 100644 index e0f7b9600945..000000000000 --- a/src/p2p/wire/messages.ts +++ /dev/null @@ -1,79 +0,0 @@ - -export interface Request { - id: number; - method_id: number; - body: string; -} - -export interface Response { - id: number; - response_code: number; - result: Buffer; -} - -// Method ID: 0 - -export interface Hello { - network_id: number; - chain_id: number; - latest_finalized_root: Buffer; - latest_finalized_epoch: number; - best_root: Buffer; - best_slot: number; -} - -// Method ID: 1 - -export interface Goodbye { - reason: number; -} - -// Method ID: 2 - -export interface GetStatus { - sha: Buffer; - user_agent: Buffer; - timestamp: number; -} - -// Method ID: 10 - -export interface RequestBeaconBlockRoots { - start_slot: number; - count: number; -} - -export interface BeaconBlockRoots { - block_root: Buffer; - slot: number; - // Doesn't currently exist as a standalone type - roots: []BlockRootSlot; -} - -// Method ID: 11 -export interface RequestBeaconBlockHeader { - // Doesn't currently exist as a standalone type - start_root: HashTreeRoot; - start_slot: number; - max_headers: number; - skip_slots: number; -} - -export interface BeaconBlockHeaders { - // Doesn't currently exist as a standalone type - headers: []BeaconBlockHeader -} - -// Method ID: 12 -export interface RequestBeaconBlockBodies { - block_roots: []HashTreeRoot; -} - -export interface BeaconBlockBodies { - block_bodies: []BeaconBlockBody; -} - -// Method ID: 13 -export interface RequestBeaconChainState { - hashes: []HashTreeRoot; -} diff --git a/src/p2p/wire/types.ts b/src/p2p/wire/types.ts deleted file mode 100644 index e6a0a0131032..000000000000 --- a/src/p2p/wire/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {Slot} from "../../types/primitive" - -export interface BlockRootSlot { - block_root: Buffer; - slot: Slot; -} - -export interface HashTreeRoot { - hash: Buffer; -} From ddf1719b4d4a85ed91af5b4b036db5b6445012b2 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 8 May 2019 00:11:55 -0400 Subject: [PATCH 11/15] Changed message properties to camelcase and added aliased types. Still have lint issues --- src/rpc/api/wire/messages.ts | 50 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/rpc/api/wire/messages.ts b/src/rpc/api/wire/messages.ts index 6885be80d900..f43a5246c5fc 100644 --- a/src/rpc/api/wire/messages.ts +++ b/src/rpc/api/wire/messages.ts @@ -1,4 +1,4 @@ -import {Slot} from "../../types/primitive"; +import {Slot, bytes32, bytes, unint8, uint16, uint64} from "../../types/primitive"; import {BlockRootSlot, HashTreeRoot} from "./types"; interface RequestBody { @@ -6,51 +6,51 @@ interface RequestBody { } export interface Request { - id: number; - method_id: number; + id: uint64; + methodId: uint16; body: RequestBody; } export interface Response { - id: number; - response_code: number; + id: uint64; + responseCode: uint16; result: Buffer; } // Method ID: 0 export interface Hello extends RequestBody { - network_id: number; - chain_id: number; - latest_finalized_root: Buffer; - latest_finalized_epoch: number; - best_root: Buffer; - best_slot: Slot; + networkId: uint64; + chainId: uint16; + latestFinalizedRoot: bytes32; + latestFinalizedEpoch: uint64; + bestRoot: bytes32; + bestSlot: Slot; } // Method ID: 1 export interface Goodbye extends RequestBody { - reason: number; + reason: uint64; } // Method ID: 2 export interface GetStatus extends RequestBody { - sha: Buffer; - user_agent: Buffer; - timestamp: number; + sha: bytes32; + userAgent: bytes; + timestamp: uint64; } // Method ID: 10 export interface BeaconBlockRootsRequest extends RequestBody { - start_slot: Slot; - count: number; + startSlot: Slot; + count: uint64; } export interface BeaconBlockRootsResponse { - block_root: Buffer; + blockRoot: bytes32; slot: Slot; // Doesn't currently exist as a standalone type roots: []BlockRootSlot; @@ -59,24 +59,24 @@ export interface BeaconBlockRootsResponse { // Method ID: 11 export interface BeaconBlockHeadersRequest extends RequestBody { // Doesn't currently exist as a standalone type - start_root: HashTreeRoot; - start_slot: Slot; - max_headers: number; - skip_slots: number; + startRoot: HashTreeRoot; + startSlot: Slot; + maxHeaders: uint64; + skipSlots: uint64; } export interface BeaconBlockHeadersResponse { // Doesn't currently exist as a standalone type - headers: []BeaconBlockHeader + headers: []BeaconBlockHeader; } // Method ID: 12 export interface BeaconBlockBodiesRequest extends RequestBody { - block_roots: []HashTreeRoot; + blockRoots: []HashTreeRoot; } export interface BeaconBlockBodiesResponse { - block_bodies: []BeaconBlockBody; + blockBodies: []BeaconBlockBody; } // Method ID: 13 From 0ac4eba8d7951f7a336c01293151a4731565d7b8 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Wed, 8 May 2019 12:51:36 -0400 Subject: [PATCH 12/15] Added protobuf file for wire protocol --- src/rpc/protocol/wire.proto | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/rpc/protocol/wire.proto diff --git a/src/rpc/protocol/wire.proto b/src/rpc/protocol/wire.proto new file mode 100644 index 000000000000..9da5d407e89f --- /dev/null +++ b/src/rpc/protocol/wire.proto @@ -0,0 +1,87 @@ +syntax = "proto3"; + +service Eth2WireProtocol { + rpc Hello (HelloRequest) returns (HelloResponse) {} + rpc Goodbye (GoodbyeRequest) returns (GoodbyeResponse) {} + rpc GetStatus (GetStatusRequest) returns (GetStatusResponse) {} + rpc BeaconBlockRoots (BeaconBlockRootsRequest) returns (BeaconBlockRootsResponse) {} + rpc BeaconBlockHeaders (BeaconBlockHeadersRequest) returns (BeaconBlockResponse) {} + rpc BeaconBlockBodies (BeaconBlockBodiesRequest) returns (BeaconBlockBodiesResponse) {} + rpc BeaconChainState (BeaconChainStateRequest) returns (BeaconChainStateResponse) {} +} + +message HelloRequest { + uint32 networkId = 1; + uint64 chainId = 2; + bytes latestFinalizedRoot = 3; + uint64 latestFinalizedEpoch = 4; + bytes bestRoot = 5; + uint64 bestSlot = 6; +} + +message HelloResponse { + uint32 networkId = 1; + uint64 chainId = 2; + bytes latestFinalizedRoot = 3; + uint64 latestFinalizedEpoch = 4; + bytes bestRoot = 5; + uint64 bestSlot = 6; +} + +message GoodbyeRequest { + uint64 reason = 1; +} + +message GoodbyeResponse { + uint64 reason = 1; +} + +message GetStatusRequest { + bytes sha = 1; + bytes userAgent = 2; + uint64 timestamp = 3; +} + +message GetStatusResponse { + bytes sha = 1; + bytes userAgent = 2; + uint64 timestamp = 3; +} + +message BeaconBlockRootsRequest { + uint64 startSlot = 1; + uint64 count = 2; +} + +message BeaconBlockRootsResponse { + bytes blockRoot = 1; + uint64 slot = 2; + repeated bytes roots = 3; +} + +message BeaconBlockHeadersRequest { + bytes startRoot = 1; + uint64 startSlot = 2; + uint64 maxHeaders = 3; + uint64 skipSlots = 4; +} + +message BeaconBlockHeadersResponse { + repeated bytes headers = 1; +} + +message BeaconBlockBodiesRequest { + repeated bytes blockRoots = 1; +} + +message BeaconBlockBodiesResponse { + repeated bytes blockBodies = 1; +} + +message BeaconChainStateRequest { + repeated bytes hashes = 1; +} + +message BeaconChainStateResponse { + +} From 712a03980fd333ff3d9ebcc5b3d42b00e4f08660 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 9 May 2019 21:21:58 -0400 Subject: [PATCH 13/15] Started refactoring to enable RPC over Libp2p --- src/p2p/index.ts | 47 ++++++++++++++++++++++++++++++++++++++++------- src/p2p/node.ts | 17 ++++++++++++++++- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/p2p/index.ts b/src/p2p/index.ts index 0845daa54675..de3ee53b402c 100644 --- a/src/p2p/index.ts +++ b/src/p2p/index.ts @@ -10,7 +10,7 @@ import {PeerId} from "peer-id"; import {promisify} from "promisify-es6"; import {Hello, Goodbye} from "../rpc/api/wire/messages"; import {DB} from "../db"; -import {BeaconChain} from "../chain" +import {BeaconChain} from "../chain"; export interface P2pOptions { maxPeers: number; @@ -98,14 +98,15 @@ export class P2PNetwork extends EventEmitter implements Service { } }); - + + /* // 2-way handshake const protocol = "/eth/serenity/beacon/rpc/1"; // Placeholders to make this file compile temporarily const helloMsg: Hello = { networkId: 0, chainId: 0, - latestFinalizedRoot: Buffer.from(""), + latestFinalizedRoot: Buffer.from(""), latestFinalizedEpoch: 0, bestRoot: Buffer.from(""), bestSlot: 0 @@ -120,11 +121,15 @@ export class P2PNetwork extends EventEmitter implements Service { }) ); }); + */ this.node.on('peer:connect', (peerInfo) => { try { this.log.info(`Peer connected: ${peerInfo}`); this.peerBook.put(peerInfo); this.discoveredPeers.add(peerInfo); + + + /* this.node.dialProtocol(peerInfo, protocol, (err, conn) => { pull( pull.values([Buffer.from(JSON.stringify(helloMsg))]), @@ -138,7 +143,7 @@ export class P2PNetwork extends EventEmitter implements Service { } catch (err) { this.log.error(err); - } + }*/ }); this.node.on('peer:disconnect', (peerInfo) => { @@ -167,8 +172,36 @@ export class P2PNetwork extends EventEmitter implements Service { return new Promise((resolve, reject) => { const handler = (err, peerInfo) => { if (err) { - return reject(err); - } + return reject(err); + } + + protobuf.load('../rpc/protocol/wire.proto').then((root) => { + this.node.on('peer:connection', (conn, peer) => { + this.log.info('peer:connection'); + + // Temporary parameters until the rest is ready. + peer.rpc.Hello({ + networkId: 0, + chainId: 0, + latestFinalizedRoot: 0x00, + latestFinalizedEpoch: 0, + bestRoot: 0x00, + bestSlot: 0, + }, + + (response, peer) => { + // Process response + }); + }); + + // Simply this. + this.node.handle('Hello', (networkId, chainId, latestFinalizedRoot, latestFinalizedEpoch, bestRoot, BestSlot, peer, response) => { + response({ + // Respond with hello message + }); + }); + }); + this.peerBook.getAll().forEach((peer) => { peer.multiaddrs.forEach((multiaddr) => { peerInfo.multiaddrs.add(multiaddr); @@ -188,4 +221,4 @@ export class P2PNetwork extends EventEmitter implements Service { } }); } -} +}i diff --git a/src/p2p/node.ts b/src/p2p/node.ts index 1f12c42c5944..d99d08d311e1 100644 --- a/src/p2p/node.ts +++ b/src/p2p/node.ts @@ -7,6 +7,7 @@ import {PeerInfo} from "peer-info"; import {PeerId} from "peer-id"; import {defaultsDeep} from "@nodeutils/defaults-deep"; import * as FloodSub from "libp2p-floodsub"; +import {protobuf} from "protobufjs"; export interface LodestarNodeOpts { bootstrap?: string[]; @@ -18,7 +19,7 @@ export class LodestarNode extends LibP2p { private pubsub: FloodSub; - private constructor(_options: LodestarNodeOpts) { + private constructor(pInfo: PeerInfo, _options: LodestarNodeOpts) { const defaults = { modules: { transport: [TCP], @@ -36,6 +37,8 @@ export class LodestarNode extends LibP2p { } }; + this.handlers = {}; + this.requests = {}; super(defaultsDeep(_options, defaults)); } @@ -56,5 +59,17 @@ export class LodestarNode extends LibP2p { await promisify(super.start.bind(this))(); await promisify(this.pubsub.start.bind(this.pubsub))(); } + + public async handle() { + + } + + private async _connection(conn: Connection, peer:): Promise { + + } + + private async _rpc(send: ): Promise { + + } } From caf7a63d8dc87a8b670ee5dc21c5c62f400722be Mon Sep 17 00:00:00 2001 From: Mikerah Date: Mon, 20 May 2019 08:48:00 -0400 Subject: [PATCH 14/15] Added packet protobuf --- src/rpc/protocol/packet.proto | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/rpc/protocol/packet.proto diff --git a/src/rpc/protocol/packet.proto b/src/rpc/protocol/packet.proto new file mode 100644 index 000000000000..db847c3d92e0 --- /dev/null +++ b/src/rpc/protocol/packet.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +message Packet { + string key = 1; + string method = 2; + string type = 3; + string dataType = 4; +} From aec549da70d020bcc09b253d7a56bdb084d12c54 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Tue, 21 May 2019 10:19:42 -0400 Subject: [PATCH 15/15] Refactoring p2p code to make it easier to do RPC over libp2p --- src/p2p/index.ts | 78 +------------------------------ src/p2p/messages/packet.proto | 8 ++++ src/p2p/messages/wire.proto | 87 +++++++++++++++++++++++++++++++++++ src/p2p/node.ts | 51 +++++++++++++++++++- 4 files changed, 146 insertions(+), 78 deletions(-) create mode 100644 src/p2p/messages/packet.proto create mode 100644 src/p2p/messages/wire.proto diff --git a/src/p2p/index.ts b/src/p2p/index.ts index de3ee53b402c..463ac1eaac40 100644 --- a/src/p2p/index.ts +++ b/src/p2p/index.ts @@ -81,80 +81,6 @@ export class P2PNetwork extends EventEmitter implements Service { peerInfo: await this.createPeerInfo(), bootnodes: this.options.bootnodes }); - - this.node.on('peer:discovery', (peerInfo) => { - try { - const peerId = peerInfo.id.toB58String(); - // Check if peer has already been discovered - if (this.options.peerBook.has(peerId) || this.discoveredPeers.has(peerId)) { - return; - } - this.peerBook.put(peerInfo); - this.node.dial(peerInfo, () => {}); - this.log.info(`Peer discovered: ${peerInfo}`); - this.emit('connected', peerInfo); - } catch (err) { - this.log.error(err); - } - - }); - - /* - // 2-way handshake - const protocol = "/eth/serenity/beacon/rpc/1"; - // Placeholders to make this file compile temporarily - const helloMsg: Hello = { - networkId: 0, - chainId: 0, - latestFinalizedRoot: Buffer.from(""), - latestFinalizedEpoch: 0, - bestRoot: Buffer.from(""), - bestSlot: 0 - }; - this.node.handle(protocol, (proto, conn) => { - pull( - pull.values([Buffer.from(JSON.stringify(helloMsg))]), - conn, - pull.collect((values) => { - // Peers' responses - - }) - ); - }); - */ - this.node.on('peer:connect', (peerInfo) => { - try { - this.log.info(`Peer connected: ${peerInfo}`); - this.peerBook.put(peerInfo); - this.discoveredPeers.add(peerInfo); - - - /* - this.node.dialProtocol(peerInfo, protocol, (err, conn) => { - pull( - pull.values([Buffer.from(JSON.stringify(helloMsg))]), - conn, - pull.collect((values) => { - // Peers responses - - }) - ); - }); - - } catch (err) { - this.log.error(err); - }*/ - }); - - this.node.on('peer:disconnect', (peerInfo) => { - try { - this.peerBook.remove(peerInfo); - this.discoveredPeers.delete(peerInfo); - } catch (err) { - this.log.error(err); - } - }); - } await promisify(this.node.start.bind(this.node))(); this.started = true; @@ -175,7 +101,7 @@ export class P2PNetwork extends EventEmitter implements Service { return reject(err); } - protobuf.load('../rpc/protocol/wire.proto').then((root) => { + protobuf.load('./messages/wire.proto').then((root) => { this.node.on('peer:connection', (conn, peer) => { this.log.info('peer:connection'); @@ -194,7 +120,7 @@ export class P2PNetwork extends EventEmitter implements Service { }); }); - // Simply this. + // Simplify this. this.node.handle('Hello', (networkId, chainId, latestFinalizedRoot, latestFinalizedEpoch, bestRoot, BestSlot, peer, response) => { response({ // Respond with hello message diff --git a/src/p2p/messages/packet.proto b/src/p2p/messages/packet.proto new file mode 100644 index 000000000000..db847c3d92e0 --- /dev/null +++ b/src/p2p/messages/packet.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +message Packet { + string key = 1; + string method = 2; + string type = 3; + string dataType = 4; +} diff --git a/src/p2p/messages/wire.proto b/src/p2p/messages/wire.proto new file mode 100644 index 000000000000..9da5d407e89f --- /dev/null +++ b/src/p2p/messages/wire.proto @@ -0,0 +1,87 @@ +syntax = "proto3"; + +service Eth2WireProtocol { + rpc Hello (HelloRequest) returns (HelloResponse) {} + rpc Goodbye (GoodbyeRequest) returns (GoodbyeResponse) {} + rpc GetStatus (GetStatusRequest) returns (GetStatusResponse) {} + rpc BeaconBlockRoots (BeaconBlockRootsRequest) returns (BeaconBlockRootsResponse) {} + rpc BeaconBlockHeaders (BeaconBlockHeadersRequest) returns (BeaconBlockResponse) {} + rpc BeaconBlockBodies (BeaconBlockBodiesRequest) returns (BeaconBlockBodiesResponse) {} + rpc BeaconChainState (BeaconChainStateRequest) returns (BeaconChainStateResponse) {} +} + +message HelloRequest { + uint32 networkId = 1; + uint64 chainId = 2; + bytes latestFinalizedRoot = 3; + uint64 latestFinalizedEpoch = 4; + bytes bestRoot = 5; + uint64 bestSlot = 6; +} + +message HelloResponse { + uint32 networkId = 1; + uint64 chainId = 2; + bytes latestFinalizedRoot = 3; + uint64 latestFinalizedEpoch = 4; + bytes bestRoot = 5; + uint64 bestSlot = 6; +} + +message GoodbyeRequest { + uint64 reason = 1; +} + +message GoodbyeResponse { + uint64 reason = 1; +} + +message GetStatusRequest { + bytes sha = 1; + bytes userAgent = 2; + uint64 timestamp = 3; +} + +message GetStatusResponse { + bytes sha = 1; + bytes userAgent = 2; + uint64 timestamp = 3; +} + +message BeaconBlockRootsRequest { + uint64 startSlot = 1; + uint64 count = 2; +} + +message BeaconBlockRootsResponse { + bytes blockRoot = 1; + uint64 slot = 2; + repeated bytes roots = 3; +} + +message BeaconBlockHeadersRequest { + bytes startRoot = 1; + uint64 startSlot = 2; + uint64 maxHeaders = 3; + uint64 skipSlots = 4; +} + +message BeaconBlockHeadersResponse { + repeated bytes headers = 1; +} + +message BeaconBlockBodiesRequest { + repeated bytes blockRoots = 1; +} + +message BeaconBlockBodiesResponse { + repeated bytes blockBodies = 1; +} + +message BeaconChainStateRequest { + repeated bytes hashes = 1; +} + +message BeaconChainStateResponse { + +} diff --git a/src/p2p/node.ts b/src/p2p/node.ts index d99d08d311e1..465db741ce7d 100644 --- a/src/p2p/node.ts +++ b/src/p2p/node.ts @@ -8,6 +8,8 @@ import {PeerId} from "peer-id"; import {defaultsDeep} from "@nodeutils/defaults-deep"; import * as FloodSub from "libp2p-floodsub"; import {protobuf} from "protobufjs"; +import logger, {AbstractLogger} from "../logger"; +import {PeerBook} from "peer-book"; export interface LodestarNodeOpts { bootstrap?: string[]; @@ -19,7 +21,11 @@ export class LodestarNode extends LibP2p { private pubsub: FloodSub; - private constructor(pInfo: PeerInfo, _options: LodestarNodeOpts) { + private log: AbstractLogger; + + private peerBook: PeerBook; + + private constructor(_options: LodestarNodeOpts) { const defaults = { modules: { transport: [TCP], @@ -39,6 +45,8 @@ export class LodestarNode extends LibP2p { this.handlers = {}; this.requests = {}; + this.peerBook = new PeerBook(); + this.log = logger; super(defaultsDeep(_options, defaults)); } @@ -56,7 +64,46 @@ export class LodestarNode extends LibP2p { } public async start(): Promise { - await promisify(super.start.bind(this))(); + const startFn = promisify(super.start.bind(this)); + await startFn((err) => { + if (err) { + this.log.info(err); + return; + } + + this.on('peer:discovery', (peerInfo) => { + this.log.info(`Discovered Peer: ${peerInfo}`); + const peerId = peerInfo.id.toB58String(); + if (peerBook.has(peerId)) { + return; + } + + this.peerBook.put(peerInfo); + + this.dialProtocol(peerInfo, 'eth/serenity/beacon/rpc/1', (err, conn) => { + if (err) { + this.log.info(`Error during dialing: ${err} `); + return; + } + + return this._connection(conn, peerInfo); + }) + }); + super.handle('eth/serenity/beacon/rpc/1', (protocol, conn) => { + return this._connection(conn, null); + }); + + this.on('peer:connect', (peerInfo) => { + this.log.info(`Peer connected: ${peerInfo}`); + this.peerBook.put(peerInfo); + }); + + this.on('peer:disconnect', (peerInfo) => { + this.log.info(`Peer disconnected: ${peerInfo}`); + this.peerBook.remote(peerInfo); + }); + + }); await promisify(this.pubsub.start.bind(this.pubsub))(); }