Skip to content

Commit

Permalink
Implement admin_addPeer (#3788)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
scorbajio and acolytec3 authored Nov 6, 2024
1 parent 974a5f4 commit e38dccc
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 191 deletions.
194 changes: 6 additions & 188 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 45 additions & 2 deletions packages/client/src/rpc/modules/admin.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { bytesToHex } from '@ethereumjs/util'

import { Config } from '../../index.js'
import { RlpxPeer } from '../../net/peer/rlpxpeer.js'
import { getClientVersion } from '../../util/index.js'
import { INTERNAL_ERROR } from '../error-code.js'
import { callWithStackTrace } from '../helpers.js'
import { middleware } from '../validation.js'
import { middleware, validators } from '../validation.js'

import type { Chain } from '../../blockchain/index.js'
import type { EthereumClient } from '../../client.js'
import type { RlpxPeer } from '../../net/peer/rlpxpeer.js'
import type { RlpxServer } from '../../net/server/rlpxserver.js'
import type { FullEthereumService } from '../../service/index.js'

/**
Expand All @@ -30,6 +33,15 @@ export class Admin {

this.nodeInfo = middleware(callWithStackTrace(this.nodeInfo.bind(this), this._rpcDebug), 0, [])
this.peers = middleware(callWithStackTrace(this.peers.bind(this), this._rpcDebug), 0, [])
this.addPeer = middleware(callWithStackTrace(this.addPeer.bind(this), this._rpcDebug), 1, [
[
validators.object({
address: validators.ipv4Address,
udpPort: validators.unsignedInteger,
tcpPort: validators.unsignedInteger,
}),
],
])
}

/**
Expand Down Expand Up @@ -97,4 +109,35 @@ export class Admin {
}
})
}

/**
* Attempts to add a peer to client service peer pool using the RLPx server address and port
* e.g. `.admin_addPeer [{"address": "127.0.0.1", "tcpPort": 30303, "udpPort": 30303}]`
* @param params An object containing an address, tcpPort, and udpPort for target server to connect to
*/
async addPeer(params: [Object]) {
const service = this._client.service as any as FullEthereumService
const server = service.pool.config.server as RlpxServer
const dpt = server.dpt

let peerInfo
try {
peerInfo = await dpt!.addPeer(params[0])
const rlpxPeer = new RlpxPeer({
config: new Config(),
id: bytesToHex(peerInfo.id!),
host: peerInfo.address!,
port: peerInfo.tcpPort as number,
})
service.pool.add(rlpxPeer)
} catch (err: any) {
throw {
code: INTERNAL_ERROR,
message: `failed to add peer: ${JSON.stringify(params)}`,
stack: err?.stack,
}
}

return peerInfo !== undefined
}
}
20 changes: 19 additions & 1 deletion packages/client/src/rpc/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,29 @@ export const validators = {
},

/**
* number validator to check if type is integer
* bool validator to check if type is valid ipv4 address
* @param params parameters of method
* @param index index of parameter
*/
get ipv4Address() {
// regex from https://stackoverflow.com/questions/5284147/validating-ipv4-addresses-with-regexp
const ipv4Regex = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/

return (params: any[], index: number) => {
if (!ipv4Regex.test(params[index])) {
return {
code: INVALID_PARAMS,
message: `invalid argument ${index}: argument is not ipv4 address`,
}
}
}
},

/**
* number validator to check if type is integer
* @param params parameters of method
* @param index index of parameter
*/
get integer() {
return (params: any[], index: number) => {
if (!Number.isInteger(params[index])) {
Expand Down
Loading

0 comments on commit e38dccc

Please sign in to comment.