Skip to content

Commit c890306

Browse files
committed
fix: better type safety and no null checks
1 parent 975cb19 commit c890306

File tree

6 files changed

+97
-54
lines changed

6 files changed

+97
-54
lines changed

packages/discv5/src/kademlia/bucket.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class Bucket extends (EventEmitter as { new (): BucketEventEmitter }) {
8282
return InsertResult.NodeExists;
8383
}
8484

85-
const isPendingNode = this.pending?.value.nodeId === value.nodeId;
85+
const isPendingNode = this.pending && this.pending.value.nodeId === value.nodeId;
8686

8787
switch (status) {
8888
case EntryStatus.Connected: {
@@ -141,7 +141,7 @@ export class Bucket extends (EventEmitter as { new (): BucketEventEmitter }) {
141141
} else {
142142
return UpdateResult.NotModified;
143143
}
144-
} else if (this.pending?.value.nodeId === value.nodeId) {
144+
} else if (this.pending && this.pending.value.nodeId === value.nodeId) {
145145
this.pending.value = value;
146146
return UpdateResult.UpdatedPending;
147147
} else {
@@ -192,7 +192,7 @@ export class Bucket extends (EventEmitter as { new (): BucketEventEmitter }) {
192192
default:
193193
throw new Error("Unreachable");
194194
}
195-
} else if (this.pending?.value.nodeId === id) {
195+
} else if (this.pending && this.pending.value.nodeId === id) {
196196
this.pending.status = status;
197197
return UpdateResult.UpdatedPending;
198198
} else {

packages/discv5/src/rateLimit/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,19 @@ export class RateLimiter implements IRateLimiter {
4343
}
4444

4545
if (!this.rateLimiterIP.allows(ip, 1)) {
46-
this.metrics?.rateLimitHitIP.inc();
46+
if (this.metrics) {
47+
this.metrics.rateLimitHitIP.inc();
48+
}
4749

4850
this.bannedIPs.set(ip, Date.now());
4951

5052
return false;
5153
}
5254

5355
if (!this.rateLimiterGlobal.allows(null, 1)) {
54-
this.metrics?.rateLimitHitTotal.inc();
56+
if (this.metrics) {
57+
this.metrics.rateLimitHitTotal.inc();
58+
}
5559
return false;
5660
}
5761

packages/discv5/src/service/addrVotes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class AddrVotes {
2222
const socketAddrStr = serializeSocketAddr(ip);
2323

2424
const prevVote = this.votes.get(voter);
25-
if (prevVote?.socketAddrStr === socketAddrStr) {
25+
if (prevVote && prevVote.socketAddrStr === socketAddrStr) {
2626
// Same vote, ignore
2727
return false;
2828
} else if (prevVote !== undefined) {

packages/discv5/src/service/service.ts

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,8 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
485485
const enr = this.findEnr(peer);
486486
if (!enr || !getSocketAddressMultiaddrOnENR(enr, this.ipMode)) {
487487
log("Lookup %s requested an unknown ENR or ENR w/o UDP", lookupId);
488-
this.activeLookups.get(lookupId)?.onFailure(peer);
488+
const lookup = this.activeLookups.get(lookupId);
489+
if (lookup) lookup.onFailure(peer);
489490
return;
490491
}
491492

@@ -512,7 +513,9 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
512513
log("Sending %s to node: %o", MessageType[activeRequest.request.type], nodeAddr);
513514
try {
514515
this.sessionService.sendRequest(activeRequest.contact, activeRequest.request);
515-
this.metrics?.sentMessageCount.inc({ type: MessageType[activeRequest.request.type] });
516+
if (this.metrics) {
517+
this.metrics.sentMessageCount.inc({ type: MessageType[activeRequest.request.type] });
518+
}
516519
} catch (e) {
517520
this.activeRequests.delete(bytesToBigint(activeRequest.request.id));
518521
log("Error sending RPC to node: %o, :Error: %s", nodeAddr, (e as Error).message);
@@ -526,7 +529,9 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
526529
log("Sending %s to node: %o", MessageType[response.type], nodeAddr);
527530
try {
528531
this.sessionService.sendResponse(nodeAddr, response);
529-
this.metrics?.sentMessageCount.inc({ type: MessageType[response.type] });
532+
if (this.metrics) {
533+
this.metrics.sentMessageCount.inc({ type: MessageType[response.type] });
534+
}
530535
} catch (e) {
531536
log("Error sending RPC to node: %o, :Error: %s", nodeAddr, (e as Error).message);
532537
}
@@ -735,7 +740,9 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
735740
*/
736741
private handleRpcRequest = (nodeAddr: INodeAddress, request: RequestMessage): void => {
737742
const requestType = MessageType[request.type];
738-
this.metrics?.rcvdMessageCount.inc({ type: requestType });
743+
if (this.metrics) {
744+
this.metrics.rcvdMessageCount.inc({ type: requestType });
745+
}
739746

740747
try {
741748
switch (request.type) {
@@ -777,7 +784,9 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
777784
log("Sending PONG response to node: %o", nodeAddr);
778785
try {
779786
this.sessionService.sendResponse(nodeAddr, pongMessage);
780-
this.metrics?.sentMessageCount.inc({ type: MessageType[MessageType.PONG] });
787+
if (this.metrics) {
788+
this.metrics.sentMessageCount.inc({ type: MessageType[MessageType.PONG] });
789+
}
781790
} catch (e) {
782791
log("Failed to send Pong. Error %s", (e as Error).message);
783792
}
@@ -809,7 +818,9 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
809818
log("Sending empty NODES response to %o", nodeAddr);
810819
try {
811820
this.sessionService.sendResponse(nodeAddr, createNodesMessage(id, 1, nodes));
812-
this.metrics?.sentMessageCount.inc({ type: MessageType[MessageType.NODES] });
821+
if (this.metrics) {
822+
this.metrics.sentMessageCount.inc({ type: MessageType[MessageType.NODES] });
823+
}
813824
} catch (e) {
814825
log("Failed to send a NODES response. Error: %s", (e as Error).message);
815826
}
@@ -828,7 +839,9 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
828839
const _nodes = nodes.slice(i, i + nodesPerPacket);
829840
try {
830841
this.sessionService.sendResponse(nodeAddr, createNodesMessage(id, total, _nodes));
831-
this.metrics?.sentMessageCount.inc({ type: MessageType[MessageType.NODES] });
842+
if (this.metrics) {
843+
this.metrics.sentMessageCount.inc({ type: MessageType[MessageType.NODES] });
844+
}
832845
} catch (e) {
833846
log("Failed to send a NODES response. Error: %s", (e as Error).message);
834847
}
@@ -847,7 +860,9 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
847860
*/
848861
private handleRpcResponse = (nodeAddr: INodeAddress, response: ResponseMessage): void => {
849862
const responseType = MessageType[response.type];
850-
this.metrics?.rcvdMessageCount.inc({ type: responseType });
863+
if (this.metrics) {
864+
this.metrics.rcvdMessageCount.inc({ type: responseType });
865+
}
851866

852867
// verify we know of the rpc id
853868

@@ -867,21 +882,25 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
867882
nodeAddr,
868883
response.id
869884
);
870-
activeRequest.callbackPromise?.reject(
871-
new CodeError(
872-
"Received a response from an nexpected address",
873-
ResponseErrorType[ResponseErrorType.WrongAddress]
874-
)
875-
);
885+
if (activeRequest.callbackPromise) {
886+
activeRequest.callbackPromise.reject(
887+
new CodeError(
888+
"Received a response from an nexpected address",
889+
ResponseErrorType[ResponseErrorType.WrongAddress]
890+
)
891+
);
892+
}
876893
return;
877894
}
878895

879896
// Check that the response type matches the request
880897
if (!requestMatchesResponse(activeRequest.request, response)) {
881898
log("Node gave an incorrect response type. Ignoring response from: %o", nodeAddr);
882-
activeRequest.callbackPromise?.reject(
883-
new CodeError("Response has incorrect response type", ResponseErrorType[ResponseErrorType.WrongResponseType])
884-
);
899+
if (activeRequest.callbackPromise) {
900+
activeRequest.callbackPromise.reject(
901+
new CodeError("Response has incorrect response type", ResponseErrorType[ResponseErrorType.WrongResponseType])
902+
);
903+
}
885904
return;
886905
}
887906

@@ -901,13 +920,16 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
901920
// TODO Implement all RPC methods
902921
return;
903922
}
904-
905-
activeRequest.callbackPromise?.resolve(toResponseType(response));
923+
if (activeRequest.callbackPromise) {
924+
activeRequest.callbackPromise.resolve(toResponseType(response));
925+
}
906926
} catch (e) {
907927
log("Error handling rpc response: node: %o response: %s", nodeAddr, responseType);
908-
activeRequest.callbackPromise?.reject(
909-
new CodeError((e as Error).message, ResponseErrorType[ResponseErrorType.InternalError])
910-
);
928+
if (activeRequest.callbackPromise) {
929+
activeRequest.callbackPromise.reject(
930+
new CodeError((e as Error).message, ResponseErrorType[ResponseErrorType.InternalError])
931+
);
932+
}
911933
}
912934
};
913935

@@ -1056,6 +1078,8 @@ export class Discv5 extends (EventEmitter as { new (): Discv5EventEmitter }) {
10561078
this.connectionUpdated(nodeId, { type: ConnectionStatusType.Disconnected });
10571079

10581080
// If this is initiated by the user, return the error on the callback.
1059-
callbackPromise?.reject(new CodeError("RPC failure", RequestErrorType[error]));
1081+
if (callbackPromise) {
1082+
callbackPromise.reject(new CodeError("RPC failure", RequestErrorType[error]));
1083+
}
10601084
};
10611085
}

packages/discv5/src/session/service.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ export class SessionService extends (EventEmitter as { new (): StrictEventEmitte
286286
// table (remote_enr is None) then we re-request the ENR to keep the session up to date.
287287

288288
// send the challenge
289-
const enrSeq = remoteEnr?.seq ?? 0n;
289+
const enrSeq = (remoteEnr && remoteEnr.seq) ?? 0n;
290290
const packet = createWhoAreYouPacket(nonce, enrSeq);
291291
const challengeData = encodeChallengeData(packet.maskingIv, packet.header);
292292

@@ -485,7 +485,9 @@ export class SessionService extends (EventEmitter as { new (): StrictEventEmitte
485485
const enrMultiaddrIP6 = getSocketAddressMultiaddrOnENR(enr, { ...this.ipMode, ip4: false } as IPMode);
486486
return (
487487
enr.nodeId === nodeAddr.nodeId &&
488-
(enrMultiaddrIP4?.equals(nodeAddr.socketAddr) ?? enrMultiaddrIP6?.equals(nodeAddr.socketAddr) ?? true)
488+
((enrMultiaddrIP4 && enrMultiaddrIP4.equals(nodeAddr.socketAddr)) ??
489+
(enrMultiaddrIP6 && enrMultiaddrIP6.equals(nodeAddr.socketAddr)) ??
490+
true)
489491
);
490492
}
491493

@@ -759,11 +761,15 @@ export class SessionService extends (EventEmitter as { new (): StrictEventEmitte
759761
}
760762

761763
private removeExpectedResponse(socketAddr: Multiaddr): void {
762-
this.transport.addExpectedResponse?.(socketAddr.toOptions().host);
764+
if (this.transport.addExpectedResponse) {
765+
this.transport.addExpectedResponse(socketAddr.toOptions().host);
766+
}
763767
}
764768

765769
private addExpectedResponse(socketAddr: Multiaddr): void {
766-
this.transport.removeExpectedResponse?.(socketAddr.toOptions().host);
770+
if (this.transport.removeExpectedResponse) {
771+
this.transport.removeExpectedResponse(socketAddr.toOptions().host);
772+
}
767773
}
768774

769775
private handleRequestTimeout(nodeAddr: INodeAddress, requestCall: IRequestCall): void {

packages/discv5/src/transport/udp.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,26 +86,29 @@ export class UDPTransportService
8686
}
8787

8888
public async start(): Promise<void> {
89-
const [socket4, socket6] = await Promise.all([
90-
this.ip4 ? openSocket(this.ip4.opts) : undefined,
91-
this.ip6 ? openSocket(this.ip6.opts) : undefined,
92-
]);
93-
if (this.ip4) {
94-
socket4?.on("message", this.handleIncoming);
95-
this.ip4.socket = socket4;
96-
}
97-
if (this.ip6) {
98-
socket6?.on("message", this.handleIncoming);
99-
this.ip6.socket = socket6;
100-
}
89+
const configs: SocketOpts[] = [];
90+
if (this.ip4) configs.push(this.ip4);
91+
if (this.ip6) configs.push(this.ip6);
92+
93+
const sockets = await Promise.all(configs.map((c) => openSocket(c.opts)));
94+
95+
configs.forEach((config, index) => {
96+
const socket = sockets[index];
97+
socket.on("message", this.handleIncoming);
98+
config.socket = socket;
99+
});
101100
}
102101

103102
public async stop(): Promise<void> {
104-
const socket4 = this.ip4?.socket;
105-
const socket6 = this.ip6?.socket;
106-
socket4?.off("message", this.handleIncoming);
107-
socket6?.off("message", this.handleIncoming);
108-
await Promise.all([closeSocket(socket4), closeSocket(socket6)]);
103+
const sockets: dgram.Socket[] = [];
104+
if (this.ip4 && this.ip4.socket) sockets.push(this.ip4.socket);
105+
if (this.ip6 && this.ip6.socket) sockets.push(this.ip6.socket);
106+
107+
sockets.forEach((socket) => {
108+
socket.off("message", this.handleIncoming);
109+
});
110+
111+
await Promise.all(sockets.map((socket) => closeSocket(socket)));
109112
}
110113

111114
public async send(to: Multiaddr, toId: string, packet: IPacket): Promise<void> {
@@ -114,21 +117,27 @@ export class UDPTransportService
114117
if (!this.ip4) {
115118
throw new Error("Cannot send to an IPv4 address without a bound IPv4 socket");
116119
}
117-
this.ip4.socket?.send(encodePacket(toId, packet), nodeAddr.port, nodeAddr.host);
120+
if (this.ip4.socket) {
121+
this.ip4.socket.send(encodePacket(toId, packet), nodeAddr.port, nodeAddr.host);
122+
}
118123
} else if (nodeAddr.family === 6) {
119124
if (!this.ip6) {
120125
throw new Error("Cannot send to an IPv6 address without a bound IPv6 socket");
121126
}
122-
this.ip6.socket?.send(encodePacket(toId, packet), nodeAddr.port, nodeAddr.host);
127+
if (this.ip6.socket) {
128+
this.ip6.socket.send(encodePacket(toId, packet), nodeAddr.port, nodeAddr.host);
129+
}
123130
}
124131
}
125132

126133
addExpectedResponse(ipAddress: string): void {
127-
this.rateLimiter?.addExpectedResponse(ipAddress);
134+
if (!this.rateLimiter) return;
135+
this.rateLimiter.addExpectedResponse(ipAddress);
128136
}
129137

130138
removeExpectedResponse(ipAddress: string): void {
131-
this.rateLimiter?.removeExpectedResponse(ipAddress);
139+
if (!this.rateLimiter) return;
140+
this.rateLimiter.removeExpectedResponse(ipAddress);
132141
}
133142

134143
getContactableAddr(enr: ENR): SocketAddress | undefined {

0 commit comments

Comments
 (0)