Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] ETH2.0 Wire protocol #195

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
dba5484
Added messages in ETH2.0 wire protocol
Mikerah Apr 29, 2019
8565457
Added messages in ETH2.0 wire protocol
Mikerah Apr 29, 2019
f5a134b
Merge branch 'mikerah/eth2-wire-protocol' of github.com:ChainSafe/lod…
Mikerah Apr 29, 2019
2da7112
Added messages in ETH2.0 wire protocol
Mikerah Apr 29, 2019
d35dd1f
Merge branch 'mikerah/eth2-wire-protocol' of github.com:ChainSafe/lod…
Mikerah May 2, 2019
93be293
Merge branch 'master' of github.com:ChainSafe/lodestar into mikerah/e…
Mikerah May 2, 2019
88d333d
Merge branch 'master' of github.com:ChainSafe/lodestar into mikerah/e…
Mikerah May 5, 2019
8698363
Completed 2-way handshake
Mikerah May 6, 2019
560d066
Refactored wire protocol api into rpc module
Mikerah May 7, 2019
5abed10
Completed RPC methods interface for wire protocol
Mikerah May 7, 2019
07ea887
Stubbed out wire.ts
Mikerah May 7, 2019
bd6752c
Forgot to change import statement to reflect refactor in p2p/index.ts
Mikerah May 7, 2019
e25b033
Added some of Marin's and Greg's suggestions
Mikerah May 8, 2019
72e2c06
Fixed lint errors in p2p/index.ts and made changes to the constructor…
Mikerah May 8, 2019
ddf1719
Changed message properties to camelcase and added aliased types. Stil…
Mikerah May 8, 2019
0ac4eba
Added protobuf file for wire protocol
Mikerah May 8, 2019
712a039
Started refactoring to enable RPC over Libp2p
Mikerah May 10, 2019
caf7a63
Added packet protobuf
Mikerah May 20, 2019
aec549d
Refactoring p2p code to make it easier to do RPC over libp2p
Mikerah May 21, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion src/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
{
Expand Down
50 changes: 46 additions & 4 deletions src/p2p/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ 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 {Hello, Goodbye} from "../rpc/api/wire/messages";
import {DB} from "../db";
import {BeaconChain} from "../chain"

export interface P2pOptions {
maxPeers: number;
Expand Down Expand Up @@ -41,15 +45,21 @@ 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;
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.chain = chain;
this.db = db;

this.started = false;
this.node = null;
Expand Down Expand Up @@ -89,18 +99,50 @@ 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(""),
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 {
GregTheGreek marked this conversation as resolved.
Show resolved Hide resolved
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);
}
});

this.node.on('peer:disconnect', (peerInfo) => {
try {
try {
this.peerBook.remove(peerInfo);
this.discoveredPeers.delete(peerInfo);
} catch (err) {
Expand Down
7 changes: 7 additions & 0 deletions src/rpc/api/wire/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {WireProtocolApi} from "./wire";
import {IWireProtocolApi} from "./interface";

export {
WireProtocolApi,
IWireProtocolApi
};
46 changes: 46 additions & 0 deletions src/rpc/api/wire/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {IApi} from "../interface";

import {
Request,
Response,
Hello,
Goodbye,
GetStatus,
BeaconBlockRootsRequest,
BeaconBlockRootsResponse,
BeaconBlockHeaderRequest,
BeaconBlockHeaderResponse,
BeaconBlockBodiesRequest,
BeaconBlockBodiesResponse,
BeaconChainStateRequest,
BeaconChainStateResponse
} from "./messages";

export interface IWireProtocolApi extends IApi {

/**
* Returns metadata about the remote node.
*/
GetStatus(): Promise<GetStatus>;

/**
* Returns list of block roots and slots from the peer
*/
RequestBeaconBlockRoots(request: BeaconBlockRootsRequest): Promise<BeaconBlockRootsResponse>;

/**
* Returns beacon block headers from peer
*/
RequestBeaconBlockHeaders(request: BeaconBlockHeadersRequest): Promise<BeaconBlockHeaderResponse>;

/**
* Returns block bodies associated with block roots from a peer
*/
RequestBeaconBlockBodies(request: BeaconBlockBodiesRequest): Promise<BeaconBlockBodiesResponse>;

/**
* Returns the hashes of merkle tree nodes from merkelizing the block's state root.
*/
RequestBeaconChainState(request: BeaconChainStateRequest): Promise<BeaconChainStateResponse>;

}
91 changes: 91 additions & 0 deletions src/rpc/api/wire/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {Slot, bytes32, bytes, unint8, uint16, uint64} from "../../types/primitive";
import {BlockRootSlot, HashTreeRoot} from "./types";

interface RequestBody {

}

export interface Request {
Mikerah marked this conversation as resolved.
Show resolved Hide resolved
id: uint64;
methodId: uint16;
body: RequestBody;
}

export interface Response {
id: uint64;
responseCode: uint16;
result: Buffer;
}

// Method ID: 0

export interface Hello extends RequestBody {
networkId: uint64;
chainId: uint16;
latestFinalizedRoot: bytes32;
latestFinalizedEpoch: uint64;
bestRoot: bytes32;
bestSlot: Slot;
}

// Method ID: 1

export interface Goodbye extends RequestBody {
reason: uint64;
}

// Method ID: 2

export interface GetStatus extends RequestBody {
sha: bytes32;
userAgent: bytes;
timestamp: uint64;
}

// Method ID: 10

export interface BeaconBlockRootsRequest extends RequestBody {
startSlot: Slot;
count: uint64;
}

export interface BeaconBlockRootsResponse {
blockRoot: bytes32;
slot: Slot;
// Doesn't currently exist as a standalone type
roots: []BlockRootSlot;
}

// Method ID: 11
export interface BeaconBlockHeadersRequest extends RequestBody {
// Doesn't currently exist as a standalone type
startRoot: HashTreeRoot;
startSlot: Slot;
maxHeaders: uint64;
skipSlots: uint64;
}

export interface BeaconBlockHeadersResponse {
// Doesn't currently exist as a standalone type
headers: []BeaconBlockHeader;
}

// Method ID: 12
export interface BeaconBlockBodiesRequest extends RequestBody {
blockRoots: []HashTreeRoot;
}

export interface BeaconBlockBodiesResponse {
blockBodies: []BeaconBlockBody;
}

// Method ID: 13
export interface BeaconChainStateRequest extends RequestBody {
hashes: []HashTreeRoot;
}

// Method ID: 14
// Not yet defined in the ETH2.0 Wire spec.
export interface BeaconChainStateResponse {

}
10 changes: 10 additions & 0 deletions src/rpc/api/wire/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Slot} from "../../types/primitive"

export interface BlockRootSlot {
block_root: Buffer;
slot: Slot;
}

export interface HashTreeRoot {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could make a Root type in src/types/primitive.ts that would be useful across the codebase, used in the wire messages.

It would look like:

export type Root = bytes32;

and since we would be using it in ssz-ed types, we'd need a export const Root = bytes32; too.

hash: Buffer;
}
58 changes: 58 additions & 0 deletions src/rpc/api/wire/wire.ts
Original file line number Diff line number Diff line change
@@ -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 = 'wire';
this.db;
this.chain;
}

public async GetStatus(): Promise<GetStatus> {

}

public async RequestBeaconBlockRoots(request: BeaconBlockRootsRequest): Promise<BeaconBlockRootsResponse> {

}

public async RequestBeaconBlockHeaders(request: BeaconBlockHeadersRequest): Promise<BeaconBlockHeadersResponse> {

}

public async RequestBeaconBlockBodies(request: BeaconBlockBodiesRequest): Promise<BeaconBlockBodiesResponse> {

}

public async RequestBeaconChainState(request: BeaconChainStateRequest): Promise<BeaconChainStateResponse> {

}

}