Skip to content

Commit

Permalink
split Engine API onto own port (default: 8550)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanio committed Oct 17, 2021
1 parent 16d696d commit 95695d2
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 39 deletions.
69 changes: 51 additions & 18 deletions packages/client/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,34 @@ const args = require('yargs')
array: true,
},
rpc: {
describe: 'Enable the JSON-RPC server',
describe: 'Enable the JSON-RPC server (default: localhost:8545)',
boolean: true,
default: Config.RPC_DEFAULT,
},
rpcport: {
describe: 'HTTP-RPC server listening port',
describe: 'HTTP-RPC server listening port (default: 8545)',
number: true,
default: Config.RPCPORT_DEFAULT,
},
rpcaddr: {
describe: 'HTTP-RPC server listening interface',
describe: 'HTTP-RPC server listening interface address (default: localhost)',
default: Config.RPCADDR_DEFAULT,
},
rpcEngine: {
describe: 'Enable merge Engine API RPC endpoints',
describe: 'Enable merge Engine API RPC endpoints on server (default: localhost:8550) ',
boolean: true,
default: Config.RPC_ENGINE_DEFAULT,
},
rpcEnginePort: {
describe: 'HTTP-RPC server listening port for Engine API (default: 8550)',
number: true,
default: Config.RPC_ENGINE_PORT_DEFAULT,
},
rpcEngineAddr: {
describe: 'HTTP-RPC server listening interface address for Engine API (default: localhost)',
string: true,
default: Config.RPC_ENGINE_ADDR_DEFAULT,
},
rpcStubGetLogs: {
describe: 'Stub eth_getLogs with empty response until method is implemented',
boolean: true,
Expand Down Expand Up @@ -219,22 +229,19 @@ async function runNode(config: Config) {
return client
}

function runRpcServer(client: EthereumClient, config: Config) {
const { rpcport, rpcaddr } = config
const manager = new RPCManager(client, config)
const server = new RPCServer(manager.getMethods())
config.logger.info(`RPC HTTP endpoint opened: http://${rpcaddr}:${rpcport}`)
server.http().listen(rpcport)

server.on('request', (request) => {
/*
* Returns enabled RPCServers
*/
function runRpcServers(client: EthereumClient, config: Config) {
const onRequest = (request: any) => {
let msg = ''
if (config.rpcDebug) {
msg += `${request.method} called with params:\n${inspectParams(request.params)}`
} else {
msg += `${request.method} called with params: ${inspectParams(request.params, 125)}`
}
config.logger.debug(msg)
})
}

const handleResponse = (request: any, response: any, batchAddOn = '') => {
let msg = ''
Expand All @@ -252,7 +259,7 @@ function runRpcServer(client: EthereumClient, config: Config) {
config.logger.debug(msg)
}

server.on('response', (request, response) => {
const onBatchResponse = (request: any, response: any) => {
// Batch request
if (request.length !== undefined) {
if (response.length === undefined || response.length !== request.length) {
Expand All @@ -265,9 +272,33 @@ function runRpcServer(client: EthereumClient, config: Config) {
} else {
handleResponse(request, response)
}
})
}

const servers: RPCServer[] = []
const { rpcaddr, rpcport, rpcEngineAddr, rpcEnginePort } = config
const manager = new RPCManager(client, config)

if (rpcport && rpcaddr) {
const server = new RPCServer(manager.getMethods())
config.logger.info(`RPC HTTP endpoint opened: http://${rpcaddr}:${rpcport}`)
server.http().listen(rpcport)
server.on('request', onRequest)
server.on('response', onBatchResponse)
servers.push(server)
}

if (rpcEnginePort && rpcEngineAddr) {
const server = new RPCServer(manager.getMethods(true))
config.logger.info(
`RPC HTTP endpoint opened for Engine API: http://${rpcEngineAddr}:${rpcEnginePort}`
)
server.http().listen(rpcEnginePort)
server.on('request', onRequest)
server.on('response', onBatchResponse)
servers.push(server)
}

return server
return servers
}

/**
Expand Down Expand Up @@ -489,6 +520,8 @@ async function run() {
rpcport: args.rpcport,
rpcaddr: args.rpcaddr,
rpcEngine: args.rpcEngine,
rpcEnginePort: args.rpcEnginePort,
rpcEngineAddr: args.rpcEngineAddr,
loglevel: args.loglevel,
rpcDebug: args.rpcDebug,
rpcStubGetLogs: args.rpcStubGetLogs,
Expand All @@ -508,11 +541,11 @@ async function run() {
config.events.setMaxListeners(50)

const client = await runNode(config)
const server = config.rpc ? runRpcServer(client, config) : null
const servers = config.rpc || config.rpcEngine ? runRpcServers(client, config) : []

process.on('SIGINT', async () => {
config.logger.info('Caught interrupt signal. Shutting down...')
if (server) server.http().close()
servers.forEach((s) => s.http().close())
await client.stop()
config.logger.info('Exiting.')
process.exit()
Expand Down
20 changes: 18 additions & 2 deletions packages/client/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,20 @@ export interface ConfigOptions {
rpcaddr?: string

/**
* Enable merge Engine API RPC endpoints
* Enable merge Engine API RPC endpoints (default: localhost:8550)
*/
rpcEngine?: boolean

/**
* HTTP-RPC server listening port for Engine API (default: 8550)
*/
rpcEnginePort?: number

/**
* HTTP-RPC server listening interface address for Engine API (default: localhost)
*/
rpcEngineAddr?: string

/**
* Until getLogs is properly implemented, stub an empty response
*/
Expand Down Expand Up @@ -229,9 +239,11 @@ export class Config {
public static readonly TRANSPORTS_DEFAULT = ['rlpx', 'libp2p']
public static readonly PORT_DEFAULT = 30303
public static readonly RPC_DEFAULT = false
public static readonly RPC_ENGINE_DEFAULT = false
public static readonly RPCPORT_DEFAULT = 8545
public static readonly RPCADDR_DEFAULT = 'localhost'
public static readonly RPC_ENGINE_DEFAULT = false
public static readonly RPC_ENGINE_PORT_DEFAULT = 8550
public static readonly RPC_ENGINE_ADDR_DEFAULT = 'localhost'
public static readonly LOGLEVEL_DEFAULT = 'info'
public static readonly RPCDEBUG_DEFAULT = false
public static readonly MAXPERREQUEST_DEFAULT = 50
Expand All @@ -254,6 +266,8 @@ export class Config {
public readonly rpcport: number
public readonly rpcaddr: string
public readonly rpcEngine: boolean
public readonly rpcEngineAddr: string
public readonly rpcEnginePort: number
public readonly loglevel: string
public readonly rpcDebug: boolean
public readonly rpcStubGetLogs: boolean
Expand Down Expand Up @@ -292,6 +306,8 @@ export class Config {
this.rpcport = options.rpcport ?? Config.RPCPORT_DEFAULT
this.rpcaddr = options.rpcaddr ?? Config.RPCADDR_DEFAULT
this.rpcEngine = options.rpcEngine ?? Config.RPC_ENGINE_DEFAULT
this.rpcEnginePort = options.rpcEnginePort ?? Config.RPC_ENGINE_PORT_DEFAULT
this.rpcEngineAddr = options.rpcEngineAddr ?? Config.RPC_ENGINE_ADDR_DEFAULT
this.loglevel = options.loglevel ?? Config.LOGLEVEL_DEFAULT
this.rpcDebug = options.rpcDebug ?? Config.RPCDEBUG_DEFAULT
this.rpcStubGetLogs = options.rpcStubGetLogs ?? false
Expand Down
29 changes: 10 additions & 19 deletions packages/client/lib/rpc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,28 @@ export class RPCManager {
}

/**
* Returns bound methods for all modules, concat with underscore `_`
* Returns bound methods for modules concat with underscore `_`
* @param engine Pass true to return only `engine_` API endpoints (default: false)
*/
getMethods() {
getMethods(engine = false) {
const methods: { [key: string]: Function } = {}
const mods = modules.list.filter((name: string) =>
engine ? name === 'Engine' : name !== 'Engine'
)

for (const modName of modules.list) {
if (modName === 'Engine' && this._config.rpcEngine === false) {
// Skip `engine_` namespace if rpcEngine is not enabled
continue
}
if (this._config.rpcDebug) {
this._config.logger.debug('='.repeat(29))
this._config.logger.debug(`RPC: Initialize ${modName} module`)
this._config.logger.debug('='.repeat(29))
}

for (const modName of mods) {
const mod = new (modules as any)[modName](this._client)
const rpcMethods = RPCManager.getMethodNames((modules as any)[modName])
for (const methodName of rpcMethods) {
if (methodName === 'getLogs' && !this._config.rpcStubGetLogs) {
continue
}
const concatedMethodName = `${modName.toLowerCase()}_${methodName}`
if (this._config.rpcDebug) {
this._config.logger.debug(`Setup method ${concatedMethodName}`)
}
methods[concatedMethodName] = mod[methodName].bind(mod)
}
if (this._config.rpcDebug) {
this._config.logger.debug('')
}
}
if (this._config.rpcDebug) {
this._config.logger.debug(`RPC Initialized ${Object.keys(methods).join(', ')}`)
}
return methods
}
Expand Down

0 comments on commit 95695d2

Please sign in to comment.