Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
55 changes: 55 additions & 0 deletions packages/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,61 @@ to help contributors better understand how the project is organized.

## Developer

### Debugging

#### Networking

##### Local Connection: EthereumJS <- EthereumJS

For debugging on networking issues there are two custom npm start scripts with appropriate settings.

Start a first client listening on the default port and using the default data directory with:

```shell
DEBUG=devp2p:* npm run client:start:dev1
DEBUG=devp2p:* npm run client:start:dev1 -- --datadir=datadir-dev1
```

Then take the enode address from the started client instance (use `127.0.0.1` for the IP address) and start a second client with:

```shell
DEBUG=devp2p:* npm run client:start:dev2 -- --bootnodes=enode://[DEV1_NODE_ID]@127.0.0.1:30303
```

This second client is using './datadir-dev2' for its data directory.

##### Local Connection: EthereumJS <- Geth

To connect Geth to a running EthereumJS instance start a client with:

```shell
DEBUG=devp2p:* npm run client:start:dev1
```

Then connect with your Geth instance via:

```shell
geth --maxpeers=1 --bootnodes=enode://[DEV1_NODE_ID]@127.0.0.1:30303
```

Depending on your use case you might want to turn off your internet connection to not allow further incoming connections on your Geth instance in case the EthereumJS connection gets disconnected.

##### Local Connection: Geth <- EthereumJS

Start your Geth instance:

```shell
geth [--syncmode=full] [--verbosity=5]
```

Note that you might want to turn off your internet connection to limit on the Geth discovery process (setting the `--nodiscover` flag won't work since this also disallows our local client from connecting).

Then connect with your EthereumJS instance via:

```shell
DEBUG=devp2p:* npm run client:start:dev2 -- --bootnodes=enode://[GETH_NODE_ID]@127.0.0.1:30303
```

### Diagram Updates

To update the structure diagram files in the root folder open the `client.drawio` file in [draw.io](https://draw.io/), make your changes, and open a PR with the updated files. Export `svg` and `png` with `border` `width=20` and `transparency=false`. For `png` go to "Advanced" and select `300 DPI`.
Expand Down
7 changes: 7 additions & 0 deletions packages/client/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ const args = require('yargs')
describe: 'Network bootnodes',
array: true,
},
port: {
describe: 'RLPx listening port',
default: Config.PORT_DEFAULT,
},
multiaddrs: {
describe: 'Network multiaddrs',
array: true,
Expand Down Expand Up @@ -176,6 +180,8 @@ async function run() {

const common = new Common({ chain, hardfork: 'chainstart' })
const datadir = args.datadir ?? Config.DATADIR_DEFAULT
const configDirectory = `${datadir}/${common.chainName()}/config`
fs.ensureDirSync(configDirectory)
const key = await Config.getClientKey(datadir, common)
const config = new Config({
common,
Expand All @@ -185,6 +191,7 @@ async function run() {
key,
transports: args.transports,
bootnodes: args.bootnodes ? parseMultiaddrs(args.bootnodes) : undefined,
port: args.port,
multiaddrs: args.multiaddrs ? parseMultiaddrs(args.multiaddrs) : undefined,
rpc: args.rpc,
rpcport: args.rpcport,
Expand Down
14 changes: 12 additions & 2 deletions packages/client/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export interface ConfigOptions {
/**
* Network transports ('rlpx' and/or 'libp2p')
*
* Default: `['rlpx:port=30303', 'libp2p']`
* Default: `['rlpx', 'libp2p']`
*/
transports?: string[]

Expand All @@ -63,6 +63,13 @@ export interface ConfigOptions {
*/
bootnodes?: Multiaddr[]

/**
* RLPx listening port
*
* Default: `30303`
*/
port?: number

/**
* Network multiaddrs for libp2p
* (e.g. /ip4/127.0.0.1/tcp/50505/p2p/QmABC)
Expand Down Expand Up @@ -167,7 +174,8 @@ export class Config {
public static readonly SYNCMODE_DEFAULT = 'full'
public static readonly LIGHTSERV_DEFAULT = false
public static readonly DATADIR_DEFAULT = `./datadir`
public static readonly TRANSPORTS_DEFAULT = ['rlpx:port=30303', 'libp2p']
public static readonly TRANSPORTS_DEFAULT = ['rlpx', 'libp2p']
public static readonly PORT_DEFAULT = 30303
public static readonly RPC_DEFAULT = false
public static readonly RPCPORT_DEFAULT = 8545
public static readonly RPCADDR_DEFAULT = 'localhost'
Expand All @@ -185,6 +193,7 @@ export class Config {
public readonly key: Buffer
public readonly transports: string[]
public readonly bootnodes?: Multiaddr[]
public readonly port?: number
public readonly multiaddrs?: Multiaddr[]
public readonly rpc: boolean
public readonly rpcport: number
Expand All @@ -208,6 +217,7 @@ export class Config {
this.lightserv = options.lightserv ?? Config.LIGHTSERV_DEFAULT
this.transports = options.transports ?? Config.TRANSPORTS_DEFAULT
this.bootnodes = options.bootnodes
this.port = options.port ?? Config.PORT_DEFAULT
this.multiaddrs = options.multiaddrs
this.datadir = options.datadir ?? Config.DATADIR_DEFAULT
this.key = options.key ?? genPrivateKey()
Expand Down
6 changes: 3 additions & 3 deletions packages/client/lib/net/peerpool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export class PeerPool extends EventEmitter {
this.noPeerPeriods += 1
if (this.noPeerPeriods >= 3) {
const promises = this.config.servers.map(async (server) => {
if (server instanceof RlpxServer) {
if (server instanceof RlpxServer && server.discovery) {
this.config.logger.info('Restarting RLPx server: bootstrap')
await server.stop()
await server.start()
Expand All @@ -215,11 +215,11 @@ export class PeerPool extends EventEmitter {
} else {
let tablesize: number | undefined = 0
this.config.servers.forEach((server) => {
if (server instanceof RlpxServer) {
if (server instanceof RlpxServer && server.discovery) {
tablesize = server.dpt?.getPeers().length
this.config.logger.info(`Looking for suited peers: peertablesize=${tablesize}`)
}
})
this.config.logger.info(`Looking for suited peers: peertablesize=${tablesize}`)
}
} else {
this.noPeerPeriods = 0
Expand Down
27 changes: 12 additions & 15 deletions packages/client/lib/net/server/rlpxserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import { RlpxPeer } from '../peer/rlpxpeer'
import { Server, ServerOptions } from './server'

export interface RlpxServerOptions extends ServerOptions {
/* Local port to listen on (default: 30303) */
port?: number

/* List of supported clients */
clientFilter?: string[]
}
Expand Down Expand Up @@ -49,7 +46,7 @@ const ignoredErrors = new RegExp(
export class RlpxServer extends Server {
private peers: Map<string, RlpxPeer> = new Map()

public port: number
public discovery: boolean
private clientFilter: string[]

public rlpx: Devp2pRLPx | null = null
Expand All @@ -65,7 +62,7 @@ export class RlpxServer extends Server {

// TODO: get the external ip from the upnp service
this.ip = '::'
this.port = options.port ?? 30303
this.discovery = options.config.discV4 || options.config.discDns
this.clientFilter = options.clientFilter ?? [
'go1.5',
'go1.6',
Expand Down Expand Up @@ -97,17 +94,17 @@ export class RlpxServer extends Server {
enode: undefined,
id: undefined,
ip: this.ip,
listenAddr: `[${this.ip}]:${this.port}`,
ports: { discovery: this.port, listener: this.port },
listenAddr: `[${this.ip}]:${this.config.port}`,
ports: { discovery: this.config.port, listener: this.config.port },
}
}
const id = this.rlpx._id.toString('hex')
return {
enode: `enode://${id}@[${this.ip}]:${this.port}`,
enode: `enode://${id}@[${this.ip}]:${this.config.port}`,
id: id,
ip: this.ip,
listenAddr: `[${this.ip}]:${this.port}`,
ports: { discovery: this.port, listener: this.port },
listenAddr: `[${this.ip}]:${this.config.port}`,
ports: { discovery: this.config.port, listener: this.config.port },
}
}

Expand Down Expand Up @@ -230,8 +227,8 @@ export class RlpxServer extends Server {

this.dpt.on('error', (e: Error) => this.error(e))

if (this.port) {
this.dpt.bind(this.port, '0.0.0.0')
if (this.config.port) {
this.dpt.bind(this.config.port, '0.0.0.0')
}
}

Expand All @@ -245,7 +242,7 @@ export class RlpxServer extends Server {
maxPeers: this.config.maxPeers,
capabilities: RlpxPeer.capabilities(Array.from(this.protocols)),
remoteClientIdFilter: this.clientFilter,
listenPort: this.port,
listenPort: this.config.port,
common: this.config.chainCommon,
})

Expand Down Expand Up @@ -301,8 +298,8 @@ export class RlpxServer extends Server {
})
})

if (this.port) {
this.rlpx.listen(this.port, '0.0.0.0')
if (this.config.port) {
this.rlpx.listen(this.config.port, '0.0.0.0')
}
}
}
2 changes: 2 additions & 0 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"prepublishOnly": "npm run build && npm run test",
"bundle": "webpack",
"client:start": "ts-node bin/cli.ts",
"client:start:dev1": "ts-node bin/cli.ts --discDns=false --discV4=false --bootnodes",
"client:start:dev2": "ts-node bin/cli.ts --discDns=false --discV4=false --transports=rlpx --port=30304 --datadir=datadir-dev2",
"coverage": "nyc npm run test && nyc report --reporter=lcov",
"docs:build": "typedoc --tsconfig tsconfig.prod.json",
"lint": "ethereumjs-config-lint",
Expand Down
4 changes: 2 additions & 2 deletions packages/client/test/net/server/rlpxserver.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ tape('[RlpxServer]', async (t) => {
const config = new Config({ loglevel: 'error', transports: [] })
const server = new RlpxServer({ config })
server.initDpt()
td.verify((server.dpt as any).bind(server.port, '0.0.0.0'))
td.verify((server.dpt as any).bind(server.config.port, '0.0.0.0'))
server.on('error', (err: any) => t.equals(err, 'err0', 'got error'))
;(server.dpt as any).emit('error', 'err0')
})
Expand All @@ -193,7 +193,7 @@ tape('[RlpxServer]', async (t) => {
td.when(RlpxPeer.prototype.accept(rlpxPeer, td.matchers.isA(RlpxServer))).thenResolve()
server.initRlpx()
td.verify(RlpxPeer.capabilities(Array.from((server as any).protocols)))
td.verify(server.rlpx!.listen(server.port, '0.0.0.0'))
td.verify(server.rlpx!.listen(server.config.port, '0.0.0.0'))
server.on('connected', (peer: any) => t.ok(peer instanceof RlpxPeer, 'connected'))
server.on('disconnected', (peer: any) => t.equals(peer.id, '01', 'disconnected'))
server.on('error', (err: Error) => t.equals(err.message, 'err0', 'got error'))
Expand Down