From 6795fa6bf937429119c2dbdd8c073129aef27c09 Mon Sep 17 00:00:00 2001 From: Scorbajio Date: Tue, 31 Oct 2023 11:37:06 -0700 Subject: [PATCH] Add rpcDebug stack collection to all rpc modules (#3127) * Add rpcDebug stack trace collection to admin rpc module * Add rpcDebug stack trace collection to engine rpc module * Add rpcDebug stack trace collection to net rpc module * Add rpcDebug stack trace collection to net txpool module --- packages/client/src/rpc/modules/admin.ts | 7 ++- packages/client/src/rpc/modules/engine.ts | 56 ++++++++++++++--------- packages/client/src/rpc/modules/net.ts | 19 ++++++-- packages/client/src/rpc/modules/txpool.ts | 10 ++-- 4 files changed, 62 insertions(+), 30 deletions(-) diff --git a/packages/client/src/rpc/modules/admin.ts b/packages/client/src/rpc/modules/admin.ts index 3ce203e966..24b89880e4 100644 --- a/packages/client/src/rpc/modules/admin.ts +++ b/packages/client/src/rpc/modules/admin.ts @@ -1,6 +1,7 @@ import { bytesToHex } from '@ethereumjs/util' import { getClientVersion } from '../../util' +import { callWithStackTrace } from '../helpers' import { middleware } from '../validation' import type { Chain } from '../../blockchain' @@ -14,17 +15,19 @@ import type { Service } from '../../service' export class Admin { readonly _chain: Chain readonly _client: EthereumClient + private _rpcDebug: boolean /** * Create admin_* RPC module * @param client Client to which the module binds */ - constructor(client: EthereumClient) { + constructor(client: EthereumClient, rpcDebug: boolean) { const service = client.services.find((s) => s.name === 'eth') as Service this._chain = service.chain this._client = client + this._rpcDebug = rpcDebug - this.nodeInfo = middleware(this.nodeInfo.bind(this), 0, []) + this.nodeInfo = middleware(callWithStackTrace(this.nodeInfo.bind(this), this._rpcDebug), 0, []) } /** diff --git a/packages/client/src/rpc/modules/engine.ts b/packages/client/src/rpc/modules/engine.ts index 7a229e074b..3a4765a373 100644 --- a/packages/client/src/rpc/modules/engine.ts +++ b/packages/client/src/rpc/modules/engine.ts @@ -23,6 +23,7 @@ import { UNSUPPORTED_FORK, validEngineCodes, } from '../error-code' +import { callWithStackTrace } from '../helpers' import { CLConnectionManager, middleware as cmMiddleware } from '../util/CLConnectionManager' import { middleware, validators } from '../validation' @@ -463,6 +464,8 @@ export class Engine { private chain: Chain private config: Config private vm: VM + private _rpcDebug: boolean + private pendingBlock: PendingBlock private connectionManager: CLConnectionManager @@ -482,11 +485,12 @@ export class Engine { * Create engine_* RPC module * @param client Client to which the module binds */ - constructor(client: EthereumClient) { + constructor(client: EthereumClient, rpcDebug: boolean) { this.client = client this.service = client.services.find((s) => s.name === 'eth') as FullEthereumService this.chain = this.service.chain this.config = this.chain.config + this._rpcDebug = rpcDebug if (this.service.execution === undefined) { throw Error('execution required for engine module') @@ -533,14 +537,14 @@ export class Engine { } this.newPayloadV1 = cmMiddleware( - middleware(this.newPayloadV1.bind(this), 1, [ + middleware(callWithStackTrace(this.newPayloadV1.bind(this), this._rpcDebug), 1, [ [validators.object(executionPayloadV1FieldValidators)], ]), ([payload], response) => this.connectionManager.lastNewPayload({ payload, response }) ) this.newPayloadV2 = cmMiddleware( - middleware(this.newPayloadV2.bind(this), 1, [ + middleware(callWithStackTrace(this.newPayloadV2.bind(this), this._rpcDebug), 1, [ [ validators.either( validators.object(executionPayloadV1FieldValidators), @@ -553,7 +557,7 @@ export class Engine { this.newPayloadV3 = cmMiddleware( middleware( - this.newPayloadV3.bind(this), + callWithStackTrace(this.newPayloadV3.bind(this), this._rpcDebug), 3, [ [validators.object(executionPayloadV3FieldValidators)], @@ -581,21 +585,21 @@ export class Engine { } this.forkchoiceUpdatedV1 = cmMiddleware( - middleware(this.forkchoiceUpdatedV1.bind(this), 1, [ + middleware(callWithStackTrace(this.forkchoiceUpdatedV1.bind(this), this._rpcDebug), 1, [ [validators.object(forkchoiceFieldValidators)], [validators.optional(validators.object(payloadAttributesFieldValidatorsV1))], ]), forkchoiceUpdatedResponseCMHandler ) this.forkchoiceUpdatedV2 = cmMiddleware( - middleware(this.forkchoiceUpdatedV2.bind(this), 1, [ + middleware(callWithStackTrace(this.forkchoiceUpdatedV2.bind(this), this._rpcDebug), 1, [ [validators.object(forkchoiceFieldValidators)], [validators.optional(validators.object(payloadAttributesFieldValidatorsV2))], ]), forkchoiceUpdatedResponseCMHandler ) this.forkchoiceUpdatedV3 = cmMiddleware( - middleware(this.forkchoiceUpdatedV3.bind(this), 1, [ + middleware(callWithStackTrace(this.forkchoiceUpdatedV3.bind(this), this._rpcDebug), 1, [ [validators.object(forkchoiceFieldValidators)], [validators.optional(validators.object(payloadAttributesFieldValidatorsV3))], ]), @@ -603,47 +607,57 @@ export class Engine { ) this.getPayloadV1 = cmMiddleware( - middleware(this.getPayloadV1.bind(this), 1, [[validators.bytes8]]), + middleware(callWithStackTrace(this.getPayloadV1.bind(this), this._rpcDebug), 1, [ + [validators.bytes8], + ]), () => this.connectionManager.updateStatus() ) this.getPayloadV2 = cmMiddleware( - middleware(this.getPayloadV2.bind(this), 1, [[validators.bytes8]]), + middleware(callWithStackTrace(this.getPayloadV2.bind(this), this._rpcDebug), 1, [ + [validators.bytes8], + ]), () => this.connectionManager.updateStatus() ) this.getPayloadV3 = cmMiddleware( - middleware(this.getPayloadV3.bind(this), 1, [[validators.bytes8]]), + middleware(callWithStackTrace(this.getPayloadV3.bind(this), this._rpcDebug), 1, [ + [validators.bytes8], + ]), () => this.connectionManager.updateStatus() ) this.exchangeTransitionConfigurationV1 = cmMiddleware( - middleware(this.exchangeTransitionConfigurationV1.bind(this), 1, [ + middleware( + callWithStackTrace(this.exchangeTransitionConfigurationV1.bind(this), this._rpcDebug), + 1, [ - validators.object({ - terminalTotalDifficulty: validators.uint256, - terminalBlockHash: validators.bytes32, - terminalBlockNumber: validators.uint64, - }), - ], - ]), + [ + validators.object({ + terminalTotalDifficulty: validators.uint256, + terminalBlockHash: validators.bytes32, + terminalBlockNumber: validators.uint64, + }), + ], + ] + ), () => this.connectionManager.updateStatus() ) this.exchangeCapabilities = cmMiddleware( - middleware(this.exchangeCapabilities.bind(this), 0, []), + middleware(callWithStackTrace(this.exchangeCapabilities.bind(this), this._rpcDebug), 0, []), () => this.connectionManager.updateStatus() ) this.getPayloadBodiesByHashV1 = cmMiddleware( - middleware(this.getPayloadBodiesByHashV1.bind(this), 1, [ + middleware(callWithStackTrace(this.getPayloadBodiesByHashV1.bind(this), this._rpcDebug), 1, [ [validators.array(validators.bytes32)], ]), () => this.connectionManager.updateStatus() ) this.getPayloadBodiesByRangeV1 = cmMiddleware( - middleware(this.getPayloadBodiesByRangeV1.bind(this), 2, [ + middleware(callWithStackTrace(this.getPayloadBodiesByRangeV1.bind(this), this._rpcDebug), 2, [ [validators.bytes8], [validators.bytes8], ]), diff --git a/packages/client/src/rpc/modules/net.ts b/packages/client/src/rpc/modules/net.ts index 531f36ae07..9179084efa 100644 --- a/packages/client/src/rpc/modules/net.ts +++ b/packages/client/src/rpc/modules/net.ts @@ -1,5 +1,6 @@ import { addHexPrefix } from '@ethereumjs/util' +import { callWithStackTrace } from '../helpers' import { middleware } from '../validation' import type { EthereumClient } from '../..' @@ -15,20 +16,30 @@ export class Net { private _chain: Chain private _client: EthereumClient private _peerPool: PeerPool + private _rpcDebug: boolean /** * Create net_* RPC module * @param client Client to which the module binds */ - constructor(client: EthereumClient) { + constructor(client: EthereumClient, rpcDebug: boolean) { const service = client.services.find((s) => s.name === 'eth') as Service this._chain = service.chain this._client = client this._peerPool = service.pool + this._rpcDebug = rpcDebug - this.version = middleware(this.version.bind(this), 0, []) - this.listening = middleware(this.listening.bind(this), 0, []) - this.peerCount = middleware(this.peerCount.bind(this), 0, []) + this.version = middleware(callWithStackTrace(this.version.bind(this), this._rpcDebug), 0, []) + this.listening = middleware( + callWithStackTrace(this.listening.bind(this), this._rpcDebug), + 0, + [] + ) + this.peerCount = middleware( + callWithStackTrace(this.peerCount.bind(this), this._rpcDebug), + 0, + [] + ) } /** diff --git a/packages/client/src/rpc/modules/txpool.ts b/packages/client/src/rpc/modules/txpool.ts index 7b7f05e745..fe4a47fb70 100644 --- a/packages/client/src/rpc/modules/txpool.ts +++ b/packages/client/src/rpc/modules/txpool.ts @@ -1,4 +1,4 @@ -import { jsonRpcTx } from '../helpers' +import { callWithStackTrace, jsonRpcTx } from '../helpers' import { middleware } from '../validation' import type { EthereumClient } from '../..' @@ -13,15 +13,19 @@ import type { VM } from '@ethereumjs/vm' export class TxPool { private _txpool: Pool private _vm: VM + private _rpcDebug: boolean + /** * Create web3_* RPC module * @param client Client to which the module binds */ - constructor(client: EthereumClient) { + constructor(client: EthereumClient, rpcDebug: boolean) { const service = client.services.find((s) => s.name === 'eth') as FullEthereumService this._txpool = service.txPool this._vm = service.execution.vm - this.content = middleware(this.content.bind(this), 0, []) + this._rpcDebug = rpcDebug + + this.content = middleware(callWithStackTrace(this.content.bind(this), this._rpcDebug), 0, []) } /**