Skip to content

Commit dd46b41

Browse files
committed
Client: add tests and config references for JSON-RPC payload limits
1 parent 0eba2ce commit dd46b41

File tree

4 files changed

+98
-8
lines changed

4 files changed

+98
-8
lines changed

packages/client/bin/repl.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { startRPCServers } from './startRPC.ts'
77
import { generateClientConfig, getArgs } from './utils.ts'
88

99
import type { Common, GenesisState } from '@ethereumjs/common'
10-
import type { Config } from '../src/config.ts'
10+
import { Config } from '../src/config.ts'
1111
import type { EthereumClient } from '../src/index.ts'
1212
import type { ClientOpts } from '../src/types.ts'
1313

@@ -42,8 +42,8 @@ const setupClient = async (
4242
jwtSecret: '',
4343
rpcEngineAuth: false,
4444
rpcCors: '',
45-
rpcEthMaxPayload: args.rpcEthMaxPayload ?? '5mb',
46-
rpcEngineMaxPayload: args.rpcEngineMaxPayload ?? '15mb',
45+
rpcEthMaxPayload: args.rpcEthMaxPayload ?? Config.RPC_ETH_MAXPAYLOAD_DEFAULT,
46+
rpcEngineMaxPayload: args.rpcEngineMaxPayload ?? Config.RPC_ENGINE_MAXPAYLOAD_DEFAULT,
4747
})
4848

4949
return { client, executionRPC: servers[0], engineRPC: servers[1] }

packages/client/bin/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,12 @@ export function getArgs(): ClientOpts {
199199
.option('rpcEthMaxPayload', {
200200
describe: 'Define max JSON payload size for eth/debug RPC requests',
201201
string: true,
202-
default: '5mb',
202+
default: Config.RPC_ETH_MAXPAYLOAD_DEFAULT,
203203
})
204204
.option('rpcEngineMaxPayload', {
205205
describe: 'Define max JSON payload size for engine RPC requests',
206206
string: true,
207-
default: '15mb',
207+
default: Config.RPC_ENGINE_MAXPAYLOAD_DEFAULT,
208208
})
209209
.option('jwtSecret', {
210210
describe: 'Provide a file containing a hex encoded jwt secret for Engine RPC server',

packages/client/src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ export class Config {
366366
public readonly events: EventEmitter<EventParams>
367367

368368
public static readonly CHAIN_DEFAULT = Mainnet
369-
public static readonly SYNCMODE_DEFAULT = SyncMode.None
369+
public static readonly SYNCMODE_DEFAULT = SyncMode.Full
370370
public static readonly DATADIR_DEFAULT = `./datadir`
371371
public static readonly PORT_DEFAULT = 30303
372372
public static readonly MAXPERREQUEST_DEFAULT = 100

packages/client/test/util/rpc.spec.ts

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('[Util/RPC]', () => {
3232
const httpServer = createRPCServerListener({
3333
server,
3434
withEngineMiddleware: { jwtSecret: new Uint8Array(32) },
35-
maxPayload: '15mb',
35+
maxPayload: Config.RPC_ETH_MAXPAYLOAD_DEFAULT,
3636
})
3737
const wsServer = createWsRPCServerListener({
3838
server,
@@ -75,7 +75,7 @@ describe('[Util/RPC]', () => {
7575
const httpServer = createRPCServerListener({
7676
server,
7777
withEngineMiddleware: { jwtSecret: new Uint8Array(32) },
78-
maxPayload: '15mb',
78+
maxPayload: Config.RPC_ENGINE_MAXPAYLOAD_DEFAULT,
7979
})
8080
const wsServer = createWsRPCServerListener({
8181
server,
@@ -86,6 +86,96 @@ describe('[Util/RPC]', () => {
8686
'should return http and ws servers',
8787
)
8888
})
89+
it('should reject oversized RPC payloads', async () => {
90+
const config = new Config({
91+
accountCache: 10000,
92+
storageCache: 1000,
93+
rpcEthMaxPayload: '1kb',
94+
rpcEngineMaxPayload: '10mb',
95+
})
96+
const client = await EthereumClient.create({ config, metaDB: new MemoryLevel() })
97+
98+
const manager = new RPCManager(client, config)
99+
const { logger } = config
100+
const methodConfig = Object.values(MethodConfig)[0]
101+
const { server } = createRPCServer(manager, {
102+
methodConfig,
103+
rpcDebug: 'eth',
104+
logger,
105+
rpcDebugVerbose: undefined as any,
106+
})
107+
108+
const ethHttpServer = createRPCServerListener({
109+
server,
110+
withEngineMiddleware: undefined,
111+
maxPayload: config.rpcEthMaxPayload,
112+
})
113+
114+
const engineHttpServer = createRPCServerListener({
115+
server,
116+
withEngineMiddleware: undefined,
117+
maxPayload: config.rpcEngineMaxPayload,
118+
})
119+
120+
const ethPort = 8545
121+
const enginePort = 8551
122+
123+
ethHttpServer.listen(ethPort)
124+
engineHttpServer.listen(enginePort)
125+
126+
const oversizedEthPayload = JSON.stringify({
127+
jsonrpc: '2.0',
128+
id: 1,
129+
method: 'eth_getBlockByNumber',
130+
params: ['latest', true],
131+
data: 'eth'.repeat(2500),
132+
})
133+
134+
const oversizedEnginePayload = JSON.stringify({
135+
jsonrpc: '2.0',
136+
id: 1,
137+
method: 'engine_newPayloadV2',
138+
params: [
139+
{
140+
baseFeePerGas: '0x',
141+
blockHash: '0x',
142+
blockNumber: '0x',
143+
extraData: '0x'.repeat(2500),
144+
feeRecipient: '0x',
145+
gasLimit: '0x',
146+
gasUsed: '0x',
147+
logsBloom: '0x',
148+
parentHash: '0x',
149+
prevRandao: '0x',
150+
receiptsRoot: '0x',
151+
stateRoot: '0x',
152+
timestamp: '0x',
153+
transactions: [],
154+
},
155+
],
156+
})
157+
158+
const resEth = await fetch(`http://localhost:${ethPort}`, {
159+
method: 'POST',
160+
body: oversizedEthPayload,
161+
headers: { 'Content-Type': 'application/json' },
162+
})
163+
164+
const resEngine = await fetch(`http://localhost:${enginePort}`, {
165+
method: 'POST',
166+
body: oversizedEnginePayload,
167+
headers: {
168+
'Content-Type': 'application/json',
169+
},
170+
})
171+
172+
assert.strictEqual(
173+
resEth.status,
174+
413,
175+
'ETH server should reject oversized payload with 413 status',
176+
)
177+
assert.strictEqual(resEngine.status, 200, 'ENGINE server should accept oversized payload')
178+
})
89179
})
90180

91181
describe('[Util/RPC/Engine eth methods]', async () => {

0 commit comments

Comments
 (0)