Skip to content

Commit e38dccc

Browse files
am1r021acolytec3
andauthored
Implement admin_addPeer (#3788)
* Implement admin_addPeer endpoint * Fix type errors * Update package-lock file * Add test for admin_addPeer * Fix admin_addPeer implementation * Ignore error * Add check for peer in pool --------- Co-authored-by: acolytec3 <[email protected]>
1 parent 974a5f4 commit e38dccc

File tree

4 files changed

+121
-191
lines changed

4 files changed

+121
-191
lines changed

package-lock.json

Lines changed: 6 additions & 188 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/client/src/rpc/modules/admin.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { bytesToHex } from '@ethereumjs/util'
22

3+
import { Config } from '../../index.js'
4+
import { RlpxPeer } from '../../net/peer/rlpxpeer.js'
35
import { getClientVersion } from '../../util/index.js'
6+
import { INTERNAL_ERROR } from '../error-code.js'
47
import { callWithStackTrace } from '../helpers.js'
5-
import { middleware } from '../validation.js'
8+
import { middleware, validators } from '../validation.js'
69

710
import type { Chain } from '../../blockchain/index.js'
811
import type { EthereumClient } from '../../client.js'
9-
import type { RlpxPeer } from '../../net/peer/rlpxpeer.js'
12+
import type { RlpxServer } from '../../net/server/rlpxserver.js'
1013
import type { FullEthereumService } from '../../service/index.js'
1114

1215
/**
@@ -30,6 +33,15 @@ export class Admin {
3033

3134
this.nodeInfo = middleware(callWithStackTrace(this.nodeInfo.bind(this), this._rpcDebug), 0, [])
3235
this.peers = middleware(callWithStackTrace(this.peers.bind(this), this._rpcDebug), 0, [])
36+
this.addPeer = middleware(callWithStackTrace(this.addPeer.bind(this), this._rpcDebug), 1, [
37+
[
38+
validators.object({
39+
address: validators.ipv4Address,
40+
udpPort: validators.unsignedInteger,
41+
tcpPort: validators.unsignedInteger,
42+
}),
43+
],
44+
])
3345
}
3446

3547
/**
@@ -97,4 +109,35 @@ export class Admin {
97109
}
98110
})
99111
}
112+
113+
/**
114+
* Attempts to add a peer to client service peer pool using the RLPx server address and port
115+
* e.g. `.admin_addPeer [{"address": "127.0.0.1", "tcpPort": 30303, "udpPort": 30303}]`
116+
* @param params An object containing an address, tcpPort, and udpPort for target server to connect to
117+
*/
118+
async addPeer(params: [Object]) {
119+
const service = this._client.service as any as FullEthereumService
120+
const server = service.pool.config.server as RlpxServer
121+
const dpt = server.dpt
122+
123+
let peerInfo
124+
try {
125+
peerInfo = await dpt!.addPeer(params[0])
126+
const rlpxPeer = new RlpxPeer({
127+
config: new Config(),
128+
id: bytesToHex(peerInfo.id!),
129+
host: peerInfo.address!,
130+
port: peerInfo.tcpPort as number,
131+
})
132+
service.pool.add(rlpxPeer)
133+
} catch (err: any) {
134+
throw {
135+
code: INTERNAL_ERROR,
136+
message: `failed to add peer: ${JSON.stringify(params)}`,
137+
stack: err?.stack,
138+
}
139+
}
140+
141+
return peerInfo !== undefined
142+
}
100143
}

packages/client/src/rpc/validation.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,29 @@ export const validators = {
307307
},
308308

309309
/**
310-
* number validator to check if type is integer
310+
* bool validator to check if type is valid ipv4 address
311311
* @param params parameters of method
312312
* @param index index of parameter
313313
*/
314+
get ipv4Address() {
315+
// regex from https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp
316+
const ipv4Regex = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/
317+
318+
return (params: any[], index: number) => {
319+
if (!ipv4Regex.test(params[index])) {
320+
return {
321+
code: INVALID_PARAMS,
322+
message: `invalid argument ${index}: argument is not ipv4 address`,
323+
}
324+
}
325+
}
326+
},
314327

328+
/**
329+
* number validator to check if type is integer
330+
* @param params parameters of method
331+
* @param index index of parameter
332+
*/
315333
get integer() {
316334
return (params: any[], index: number) => {
317335
if (!Number.isInteger(params[index])) {

0 commit comments

Comments
 (0)