@streamr/trackerless-network 100.0.0-testnet-three.3 → 100.0.0-testnet-three.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +57 -0
  2. package/dist/package.json +55 -0
  3. package/dist/src/NetworkNode.js.map +1 -1
  4. package/dist/src/NetworkStack.js +7 -2
  5. package/dist/src/NetworkStack.js.map +1 -1
  6. package/dist/src/exports.d.ts +2 -1
  7. package/dist/src/exports.js +4 -1
  8. package/dist/src/exports.js.map +1 -1
  9. package/dist/src/logic/createRandomGraphNode.js +5 -2
  10. package/dist/src/logic/createRandomGraphNode.js.map +1 -1
  11. package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +1 -1
  12. package/dist/src/logic/neighbor-discovery/Handshaker.js +17 -15
  13. package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
  14. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +2 -1
  15. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
  16. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.d.ts +2 -1
  17. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js +1 -1
  18. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -1
  19. package/dist/src/logic/node-info/NodeInfoRpcLocal.js +3 -1
  20. package/dist/src/logic/node-info/NodeInfoRpcLocal.js.map +1 -1
  21. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.d.ts +4 -0
  22. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js +2 -1
  23. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +1 -1
  24. package/package.json +6 -6
  25. package/protos/NetworkRpc.proto +1 -0
  26. package/src/NetworkNode.ts +1 -1
  27. package/src/NetworkStack.ts +9 -3
  28. package/src/exports.ts +2 -1
  29. package/src/logic/createRandomGraphNode.ts +5 -2
  30. package/src/logic/neighbor-discovery/Handshaker.ts +20 -15
  31. package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +2 -1
  32. package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +3 -2
  33. package/src/logic/node-info/NodeInfoRpcLocal.ts +3 -1
  34. package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +6 -1
  35. package/test/end-to-end/inspect.test.ts +3 -3
  36. package/test/end-to-end/proxy-and-full-node.test.ts +12 -12
  37. package/test/end-to-end/proxy-connections.test.ts +7 -7
  38. package/test/end-to-end/proxy-key-exchange.test.ts +5 -5
  39. package/test/end-to-end/webrtc-full-node-network.test.ts +6 -6
  40. package/test/end-to-end/websocket-full-node-network.test.ts +6 -6
  41. package/test/integration/Handshakes.test.ts +2 -1
  42. package/test/integration/NetworkStack.test.ts +2 -2
  43. package/test/integration/NodeInfoRpc.test.ts +2 -1
  44. package/test/unit/GroupKeyResponseTranslator.test.ts +1 -1
  45. package/test/unit/Handshaker.test.ts +2 -1
  46. package/test/unit/NeighborUpdateRpcLocal.test.ts +16 -2
  47. package/tsconfig.jest.json +2 -1
  48. package/tsconfig.node.json +2 -1
@@ -175,4 +175,5 @@ message NodeInfoResponse {
175
175
  dht.PeerDescriptor peerDescriptor = 1;
176
176
  repeated StreamPartitionInfo streamPartitions = 2;
177
177
  optional ControlLayerInfo controlLayer = 3;
178
+ string version = 4;
178
179
  }
@@ -73,7 +73,7 @@ export class NetworkNode {
73
73
  }
74
74
 
75
75
  setStreamPartEntryPoints(streamPartId: StreamPartID, contactPeerDescriptors: PeerDescriptor[]): void {
76
- this.stack.getStreamrNode()!.setStreamPartEntryPoints(streamPartId, contactPeerDescriptors)
76
+ this.stack.getStreamrNode().setStreamPartEntryPoints(streamPartId, contactPeerDescriptors)
77
77
  }
78
78
 
79
79
  removeMessageListener(cb: (msg: StreamMessage) => void): void {
@@ -1,6 +1,6 @@
1
1
  import { ConnectionManager, DhtNode, DhtNodeOptions, ListeningRpcCommunicator, PeerDescriptor, areEqualPeerDescriptors } from '@streamr/dht'
2
2
  import { StreamrNode, StreamrNodeConfig } from './logic/StreamrNode'
3
- import { MetricsContext, waitForCondition } from '@streamr/utils'
3
+ import { Logger, MetricsContext, waitForCondition } from '@streamr/utils'
4
4
  import { StreamID, StreamPartID, toStreamPartID } from '@streamr/protocol'
5
5
  import { NodeInfoResponse, ProxyDirection, StreamMessage, StreamMessageType } from './proto/packages/trackerless-network/protos/NetworkRpc'
6
6
  import { Layer0Node } from './logic/Layer0Node'
@@ -14,6 +14,8 @@ export interface NetworkOptions {
14
14
  metricsContext?: MetricsContext
15
15
  }
16
16
 
17
+ const logger = new Logger(module)
18
+
17
19
  const instances: NetworkStack[] = []
18
20
  const stopInstances = async () => {
19
21
  // make a clone so that it is ok for each instance.stop() to remove itself from the list (at line 139)
@@ -23,9 +25,13 @@ const stopInstances = async () => {
23
25
  }
24
26
  const EXIT_EVENTS = [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`, `unhandledRejection`, `SIGTERM`]
25
27
  EXIT_EVENTS.forEach((event) => {
26
- process.on(event, async () => {
28
+ process.on(event, async (eventArg) => {
29
+ const isError = (event === 'uncaughtException') || (event === 'unhandledRejection')
30
+ if (isError) {
31
+ logger.error(`exit event: ${event}`, eventArg)
32
+ }
27
33
  await stopInstances()
28
- process.exit()
34
+ process.exit(isError ? 1 : 0)
29
35
  })
30
36
  })
31
37
  declare let window: any
package/src/exports.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  export { NetworkStack, NetworkOptions } from './NetworkStack'
2
2
  export { NetworkNode, createNetworkNode } from './NetworkNode'
3
3
  export { StreamrNodeConfig } from './logic/StreamrNode'
4
- export { ProxyDirection } from './proto/packages/trackerless-network/protos/NetworkRpc'
4
+ export { ProxyDirection, NodeInfoResponse } from './proto/packages/trackerless-network/protos/NetworkRpc'
5
+ export { streamPartIdToDataKey } from './logic/EntryPointDiscovery'
5
6
  export {
6
7
  convertStreamMessageToBytes,
7
8
  convertBytesToStreamMessage
@@ -37,6 +37,7 @@ const createConfigWithDefaults = (config: RandomGraphNodeConfig): StrictRandomGr
37
37
  const nearbyNodeView = config.nearbyNodeView ?? new NodeList(ownNodeId, maxContactCount)
38
38
  const randomNodeView = config.randomNodeView ?? new NodeList(ownNodeId, maxContactCount)
39
39
  const neighbors = config.neighbors ?? new NodeList(ownNodeId, maxContactCount)
40
+ const ongoingHandshakes = new Set<DhtAddress>()
40
41
 
41
42
  const temporaryConnectionRpcLocal = new TemporaryConnectionRpcLocal({
42
43
  rpcCommunicator,
@@ -70,7 +71,8 @@ const createConfigWithDefaults = (config: RandomGraphNodeConfig): StrictRandomGr
70
71
  randomNodeView,
71
72
  neighbors,
72
73
  maxNeighborCount: neighborTargetCount,
73
- rpcRequestTimeout: config.rpcRequestTimeout
74
+ rpcRequestTimeout: config.rpcRequestTimeout,
75
+ ongoingHandshakes
74
76
  })
75
77
  const neighborFinder = config.neighborFinder ?? new NeighborFinder({
76
78
  neighbors,
@@ -87,7 +89,8 @@ const createConfigWithDefaults = (config: RandomGraphNodeConfig): StrictRandomGr
87
89
  rpcCommunicator,
88
90
  neighborUpdateInterval,
89
91
  neighborTargetCount,
90
- connectionLocker: config.connectionLocker
92
+ connectionLocker: config.connectionLocker,
93
+ ongoingHandshakes
91
94
  })
92
95
  const inspector = config.inspector ?? new Inspector({
93
96
  localPeerDescriptor: config.localPeerDescriptor,
@@ -25,6 +25,7 @@ interface HandshakerConfig {
25
25
  randomNodeView: NodeList
26
26
  rpcCommunicator: ListeningRpcCommunicator
27
27
  maxNeighborCount: number
28
+ ongoingHandshakes: Set<DhtAddress>
28
29
  rpcRequestTimeout?: number
29
30
  }
30
31
 
@@ -34,7 +35,6 @@ const PARALLEL_HANDSHAKE_COUNT = 2
34
35
 
35
36
  export class Handshaker {
36
37
 
37
- private readonly ongoingHandshakes: Set<DhtAddress> = new Set()
38
38
  private config: HandshakerConfig
39
39
  private readonly rpcLocal: IHandshakeRpc
40
40
 
@@ -44,7 +44,7 @@ export class Handshaker {
44
44
  streamPartId: this.config.streamPartId,
45
45
  neighbors: this.config.neighbors,
46
46
  connectionLocker: this.config.connectionLocker,
47
- ongoingHandshakes: this.ongoingHandshakes,
47
+ ongoingHandshakes: this.config.ongoingHandshakes,
48
48
  ongoingInterleaves: new Set(),
49
49
  maxNeighborCount: this.config.maxNeighborCount,
50
50
  handshakeWithInterleaving: (target: PeerDescriptor, senderId: DhtAddress) => this.handshakeWithInterleaving(target, senderId),
@@ -59,10 +59,10 @@ export class Handshaker {
59
59
 
60
60
  async attemptHandshakesOnContacts(excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
61
61
  // TODO use config option or named constant? or why the value 2?
62
- if (this.config.neighbors.size() + this.ongoingHandshakes.size < this.config.maxNeighborCount - 2) {
62
+ if (this.config.neighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount - 2) {
63
63
  logger.trace(`Attempting parallel handshakes with ${PARALLEL_HANDSHAKE_COUNT} targets`)
64
64
  return this.selectParallelTargetsAndHandshake(excludedIds)
65
- } else if (this.config.neighbors.size() + this.ongoingHandshakes.size < this.config.maxNeighborCount) {
65
+ } else if (this.config.neighbors.size() + this.config.ongoingHandshakes.size < this.config.maxNeighborCount) {
66
66
  logger.trace(`Attempting handshake with new target`)
67
67
  return this.selectNewTargetAndHandshake(excludedIds)
68
68
  }
@@ -72,17 +72,22 @@ export class Handshaker {
72
72
  private async selectParallelTargetsAndHandshake(excludedIds: DhtAddress[]): Promise<DhtAddress[]> {
73
73
  const exclude = excludedIds.concat(this.config.neighbors.getIds())
74
74
  const neighbors = this.selectParallelTargets(exclude)
75
- neighbors.forEach((contact) => this.ongoingHandshakes.add(getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())))
75
+ neighbors.forEach((contact) => this.config.ongoingHandshakes.add(getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())))
76
76
  return this.doParallelHandshakes(neighbors, exclude)
77
77
  }
78
78
 
79
79
  private selectParallelTargets(excludedIds: DhtAddress[]): HandshakeRpcRemote[] {
80
80
  const neighbors = this.config.nearbyNodeView.getFirstAndLast(excludedIds)
81
- while (neighbors.length < PARALLEL_HANDSHAKE_COUNT && this.config.randomNodeView.size(excludedIds) > 0) {
82
- const random = this.config.randomNodeView.getRandom(excludedIds)
83
- if (random) {
84
- neighbors.push(random)
85
- }
81
+ const getExcludedFromRandomView = () => [
82
+ ...excludedIds,
83
+ ...neighbors.map((neighbor) => getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor()))
84
+ ]
85
+ while (
86
+ neighbors.length < PARALLEL_HANDSHAKE_COUNT
87
+ && this.config.randomNodeView.size(getExcludedFromRandomView()) > 0
88
+ ) {
89
+ const random = this.config.randomNodeView.getRandom(getExcludedFromRandomView())!
90
+ neighbors.push(random)
86
91
  }
87
92
  return neighbors.map((neighbor) => this.createRpcRemote(neighbor.getPeerDescriptor()))
88
93
  }
@@ -118,7 +123,7 @@ export class Handshaker {
118
123
 
119
124
  private async handshakeWithTarget(neighbor: HandshakeRpcRemote, concurrentNodeId?: DhtAddress): Promise<boolean> {
120
125
  const targetNodeId = getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor())
121
- this.ongoingHandshakes.add(targetNodeId)
126
+ this.config.ongoingHandshakes.add(targetNodeId)
122
127
  const result = await neighbor.handshake(
123
128
  this.config.streamPartId,
124
129
  this.config.neighbors.getIds(),
@@ -131,14 +136,14 @@ export class Handshaker {
131
136
  if (result.interleaveTargetDescriptor) {
132
137
  await this.handshakeWithInterleaving(result.interleaveTargetDescriptor, targetNodeId)
133
138
  }
134
- this.ongoingHandshakes.delete(targetNodeId)
139
+ this.config.ongoingHandshakes.delete(targetNodeId)
135
140
  return result.accepted
136
141
  }
137
142
 
138
143
  private async handshakeWithInterleaving(target: PeerDescriptor, interleaveSourceId: DhtAddress): Promise<boolean> {
139
144
  const neighbor = this.createRpcRemote(target)
140
145
  const targetNodeId = getNodeIdFromPeerDescriptor(neighbor.getPeerDescriptor())
141
- this.ongoingHandshakes.add(targetNodeId)
146
+ this.config.ongoingHandshakes.add(targetNodeId)
142
147
  const result = await neighbor.handshake(
143
148
  this.config.streamPartId,
144
149
  this.config.neighbors.getIds(),
@@ -149,7 +154,7 @@ export class Handshaker {
149
154
  this.config.neighbors.add(this.createDeliveryRpcRemote(neighbor.getPeerDescriptor()))
150
155
  this.config.connectionLocker.lockConnection(neighbor.getPeerDescriptor(), this.config.streamPartId)
151
156
  }
152
- this.ongoingHandshakes.delete(targetNodeId)
157
+ this.config.ongoingHandshakes.delete(targetNodeId)
153
158
  return result.accepted
154
159
  }
155
160
 
@@ -174,7 +179,7 @@ export class Handshaker {
174
179
  }
175
180
 
176
181
  getOngoingHandshakes(): Set<DhtAddress> {
177
- return this.ongoingHandshakes
182
+ return this.config.ongoingHandshakes
178
183
  }
179
184
 
180
185
  }
@@ -1,5 +1,5 @@
1
1
  import { NeighborUpdate } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
2
- import { ConnectionLocker, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
2
+ import { ConnectionLocker, DhtAddress, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
3
3
  import { NeighborUpdateRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
4
4
  import { Logger, scheduleAtInterval } from '@streamr/utils'
5
5
  import { NeighborFinder } from './NeighborFinder'
@@ -18,6 +18,7 @@ interface NeighborUpdateManagerConfig {
18
18
  rpcCommunicator: ListeningRpcCommunicator
19
19
  neighborUpdateInterval: number
20
20
  neighborTargetCount: number
21
+ ongoingHandshakes: Set<DhtAddress>
21
22
  }
22
23
 
23
24
  const logger = new Logger(module)
@@ -1,5 +1,5 @@
1
1
  import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
- import { ConnectionLocker, DhtCallContext, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
2
+ import { ConnectionLocker, DhtAddress, DhtCallContext, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
3
3
  import { NeighborUpdate } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
4
4
  import { DeliveryRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
5
5
  import { INeighborUpdateRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
@@ -17,6 +17,7 @@ interface NeighborUpdateRpcLocalConfig {
17
17
  connectionLocker: ConnectionLocker
18
18
  rpcCommunicator: ListeningRpcCommunicator
19
19
  neighborTargetCount: number
20
+ ongoingHandshakes: Set<DhtAddress>
20
21
  }
21
22
 
22
23
  export class NeighborUpdateRpcLocal implements INeighborUpdateRpc {
@@ -56,7 +57,7 @@ export class NeighborUpdateRpcLocal implements INeighborUpdateRpc {
56
57
  const senderPeerDescriptor = (context as DhtCallContext).incomingSourceDescriptor!
57
58
  const senderId = getNodeIdFromPeerDescriptor(senderPeerDescriptor)
58
59
  this.updateContacts(message.neighborDescriptors)
59
- if (!this.config.neighbors.has(senderId)) {
60
+ if (!this.config.neighbors.has(senderId) && !this.config.ongoingHandshakes.has(senderId)) {
60
61
  return this.createResponse(true)
61
62
  } else {
62
63
  const isOverNeighborCount = this.config.neighbors.size() > this.config.neighborTargetCount
@@ -2,6 +2,7 @@ import { NodeInfoRequest, NodeInfoResponse } from '../../proto/packages/trackerl
2
2
  import { INodeInfoRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
3
3
  import { NetworkStack } from '../../NetworkStack'
4
4
  import { ListeningRpcCommunicator } from '@streamr/dht'
5
+ import { version as localVersion } from '../../../package.json'
5
6
 
6
7
  export const NODE_INFO_RPC_SERVICE_ID = 'system/node-info-rpc'
7
8
 
@@ -28,7 +29,8 @@ export class NodeInfoRpcLocal implements INodeInfoRpc {
28
29
  connections: this.stack.getLayer0Node().getConnections(),
29
30
  neighbors: this.stack.getLayer0Node().getNeighbors()
30
31
  },
31
- streamPartitions: this.stack.getStreamrNode().getNodeInfo()
32
+ streamPartitions: this.stack.getStreamrNode().getNodeInfo(),
33
+ version: localVersion
32
34
  }
33
35
  }
34
36
 
@@ -329,6 +329,10 @@ export interface NodeInfoResponse {
329
329
  * @generated from protobuf field: optional ControlLayerInfo controlLayer = 3;
330
330
  */
331
331
  controlLayer?: ControlLayerInfo;
332
+ /**
333
+ * @generated from protobuf field: string version = 4;
334
+ */
335
+ version: string;
332
336
  }
333
337
  /**
334
338
  * @generated from protobuf enum StreamMessageType
@@ -673,7 +677,8 @@ class NodeInfoResponse$Type extends MessageType<NodeInfoResponse> {
673
677
  super("NodeInfoResponse", [
674
678
  { no: 1, name: "peerDescriptor", kind: "message", T: () => PeerDescriptor },
675
679
  { no: 2, name: "streamPartitions", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => StreamPartitionInfo },
676
- { no: 3, name: "controlLayer", kind: "message", T: () => ControlLayerInfo }
680
+ { no: 3, name: "controlLayer", kind: "message", T: () => ControlLayerInfo },
681
+ { no: 4, name: "version", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
677
682
  ]);
678
683
  }
679
684
  }
@@ -96,9 +96,9 @@ describe('inspect', () => {
96
96
  await inspectedNode.start()
97
97
  await inspectorNode.start()
98
98
 
99
- publisherNode.stack.getStreamrNode()!.joinStreamPart(STREAM_PART_ID)
100
- inspectedNode.stack.getStreamrNode()!.joinStreamPart(STREAM_PART_ID)
101
- inspectorNode.stack.getStreamrNode()!.joinStreamPart(STREAM_PART_ID)
99
+ publisherNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
100
+ inspectedNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
101
+ inspectorNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
102
102
 
103
103
  await waitForCondition(() =>
104
104
  publisherNode.stack.getStreamrNode().getNeighbors(STREAM_PART_ID).length === 2
@@ -65,11 +65,11 @@ describe('proxy and full node', () => {
65
65
  }
66
66
  })
67
67
  await proxyNode.start()
68
- proxyNode.stack.getStreamrNode()!.joinStreamPart(proxiedStreamPart)
69
- proxyNode.stack.getStreamrNode()!.joinStreamPart(regularStreamPart1)
70
- proxyNode.stack.getStreamrNode()!.joinStreamPart(regularStreamPart2)
71
- proxyNode.stack.getStreamrNode()!.joinStreamPart(regularStreamPart3)
72
- proxyNode.stack.getStreamrNode()!.joinStreamPart(regularStreamPart4)
68
+ proxyNode.stack.getStreamrNode().joinStreamPart(proxiedStreamPart)
69
+ proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart1)
70
+ proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart2)
71
+ proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart3)
72
+ proxyNode.stack.getStreamrNode().joinStreamPart(regularStreamPart4)
73
73
 
74
74
  proxiedNode = createNetworkNode({
75
75
  layer0: {
@@ -90,14 +90,14 @@ describe('proxy and full node', () => {
90
90
  expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(false)
91
91
 
92
92
  await Promise.all([
93
- waitForEvent3(proxyNode.stack.getStreamrNode()! as any, 'newMessage'),
93
+ waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage'),
94
94
  proxiedNode.broadcast(createMessage(regularStreamPart1))
95
95
  ])
96
96
 
97
97
  expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(true)
98
98
 
99
99
  await Promise.all([
100
- waitForEvent3(proxyNode.stack.getStreamrNode()! as any, 'newMessage'),
100
+ waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage'),
101
101
  proxiedNode.broadcast(createMessage(proxiedStreamPart))
102
102
  ])
103
103
 
@@ -110,13 +110,13 @@ describe('proxy and full node', () => {
110
110
  expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(false)
111
111
 
112
112
  await Promise.all([
113
- waitForEvent3(proxyNode.stack.getStreamrNode()! as any, 'newMessage', 5000,
113
+ waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
114
114
  (streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart1)),
115
- waitForEvent3(proxyNode.stack.getStreamrNode()! as any, 'newMessage', 5000,
115
+ waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
116
116
  (streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart2)),
117
- waitForEvent3(proxyNode.stack.getStreamrNode()! as any, 'newMessage', 5000,
117
+ waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
118
118
  (streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart3)),
119
- waitForEvent3(proxyNode.stack.getStreamrNode()! as any, 'newMessage', 5000,
119
+ waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage', 5000,
120
120
  (streamMessage: InternalStreamMessage) => streamMessage.messageId!.streamId === StreamPartIDUtils.getStreamID(regularStreamPart4)),
121
121
  proxiedNode.broadcast(createMessage(regularStreamPart1)),
122
122
  proxiedNode.broadcast(createMessage(regularStreamPart2)),
@@ -127,7 +127,7 @@ describe('proxy and full node', () => {
127
127
  expect(proxiedNode.stack.getLayer0Node().hasJoined()).toBe(true)
128
128
 
129
129
  await Promise.all([
130
- waitForEvent3(proxyNode.stack.getStreamrNode()! as any, 'newMessage'),
130
+ waitForEvent3(proxyNode.stack.getStreamrNode() as any, 'newMessage'),
131
131
  proxiedNode.broadcast(createMessage(proxiedStreamPart))
132
132
  ])
133
133
 
@@ -46,14 +46,14 @@ describe('Proxy connections', () => {
46
46
  let proxiedNode: NetworkNode
47
47
 
48
48
  const hasConnectionFromProxy = (proxyNode: NetworkNode): boolean => {
49
- const delivery = proxyNode.stack.getStreamrNode()!.getStreamPartDelivery(STREAM_PART_ID)
49
+ const delivery = proxyNode.stack.getStreamrNode().getStreamPartDelivery(STREAM_PART_ID)
50
50
  return (delivery !== undefined)
51
51
  ? ((delivery as { node: RandomGraphNode }).node).hasProxyConnection(proxiedNode.getNodeId())
52
52
  : false
53
53
  }
54
54
 
55
55
  const hasConnectionToProxy = (proxyNodeId: DhtAddress, direction: ProxyDirection): boolean => {
56
- const client = (proxiedNode.stack.getStreamrNode()!.getStreamPartDelivery(STREAM_PART_ID) as { client: ProxyClient }).client
56
+ const client = (proxiedNode.stack.getStreamrNode().getStreamPartDelivery(STREAM_PART_ID) as { client: ProxyClient }).client
57
57
  return client.hasConnection(proxyNodeId, direction)
58
58
  }
59
59
 
@@ -77,7 +77,7 @@ describe('Proxy connections', () => {
77
77
  })
78
78
  await proxyNode1.start()
79
79
  proxyNode1.setStreamPartEntryPoints(STREAM_PART_ID, [proxyNodeDescriptor1])
80
- proxyNode1.stack.getStreamrNode()!.joinStreamPart(STREAM_PART_ID)
80
+ proxyNode1.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
81
81
  proxyNode2 = createNetworkNode({
82
82
  layer0: {
83
83
  entryPoints: [proxyNodeDescriptor1],
@@ -90,7 +90,7 @@ describe('Proxy connections', () => {
90
90
  })
91
91
  await proxyNode2.start()
92
92
  proxyNode2.setStreamPartEntryPoints(STREAM_PART_ID, [proxyNodeDescriptor1])
93
- proxyNode2.stack.getStreamrNode()!.joinStreamPart(STREAM_PART_ID)
93
+ proxyNode2.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
94
94
  proxiedNode = createNetworkNode({
95
95
  layer0: {
96
96
  entryPoints: [proxyNode1.getPeerDescriptor()],
@@ -109,7 +109,7 @@ describe('Proxy connections', () => {
109
109
  it('happy path publishing', async () => {
110
110
  await proxiedNode.setProxies(STREAM_PART_ID, [proxyNode1.getPeerDescriptor()], ProxyDirection.PUBLISH, PROXIED_NODE_USER_ID, 1)
111
111
  await Promise.all([
112
- waitForEvent3(proxyNode1.stack.getStreamrNode()! as any, 'newMessage'),
112
+ waitForEvent3(proxyNode1.stack.getStreamrNode() as any, 'newMessage'),
113
113
  proxiedNode.broadcast(MESSAGE)
114
114
  ])
115
115
  })
@@ -117,7 +117,7 @@ describe('Proxy connections', () => {
117
117
  it('happy path subscribing', async () => {
118
118
  await proxiedNode.setProxies(STREAM_PART_ID, [proxyNode1.getPeerDescriptor()], ProxyDirection.SUBSCRIBE, PROXIED_NODE_USER_ID, 1)
119
119
  await Promise.all([
120
- waitForEvent3(proxiedNode.stack.getStreamrNode()! as any, 'newMessage'),
120
+ waitForEvent3(proxiedNode.stack.getStreamrNode() as any, 'newMessage'),
121
121
  proxyNode1.broadcast(MESSAGE)
122
122
  ])
123
123
  })
@@ -196,7 +196,7 @@ describe('Proxy connections', () => {
196
196
  await proxyNode1.leave(STREAM_PART_ID)
197
197
  await waitForCondition(() => hasConnectionToProxy(proxyNode1.getNodeId(), ProxyDirection.SUBSCRIBE))
198
198
  expect(hasConnectionFromProxy(proxyNode1)).toBe(false)
199
- proxyNode1.stack.getStreamrNode()!.joinStreamPart(STREAM_PART_ID)
199
+ proxyNode1.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
200
200
  await waitForCondition(() => hasConnectionToProxy(proxyNode1.getNodeId(), ProxyDirection.SUBSCRIBE), 25000)
201
201
  // TODO why wait is needed?
202
202
  await wait(100)
@@ -44,10 +44,10 @@ describe('proxy group key exchange', () => {
44
44
  })
45
45
  await proxyNode.start()
46
46
  proxyNode.setStreamPartEntryPoints(STREAM_PART_ID, [proxyNodeDescriptor])
47
- proxyNode.stack.getStreamrNode()!.joinStreamPart(STREAM_PART_ID)
47
+ proxyNode.stack.getStreamrNode().joinStreamPart(STREAM_PART_ID)
48
48
  publisher = createNetworkNode({
49
49
  layer0: {
50
- entryPoints: [publisherDescriptor],
50
+ entryPoints: [proxyNodeDescriptor],
51
51
  peerDescriptor: publisherDescriptor,
52
52
  }
53
53
  })
@@ -55,7 +55,7 @@ describe('proxy group key exchange', () => {
55
55
 
56
56
  subscriber = createNetworkNode({
57
57
  layer0: {
58
- entryPoints: [subscriberDescriptor],
58
+ entryPoints: [proxyNodeDescriptor],
59
59
  peerDescriptor: subscriberDescriptor,
60
60
  }
61
61
  })
@@ -98,7 +98,7 @@ describe('proxy group key exchange', () => {
98
98
  })
99
99
 
100
100
  await Promise.all([
101
- waitForEvent3(publisher.stack.getStreamrNode()! as any, 'newMessage'),
101
+ waitForEvent3(publisher.stack.getStreamrNode() as any, 'newMessage'),
102
102
  subscriber.broadcast(request)
103
103
  ])
104
104
  })
@@ -130,7 +130,7 @@ describe('proxy group key exchange', () => {
130
130
  })
131
131
 
132
132
  await Promise.all([
133
- waitForEvent3(subscriber.stack.getStreamrNode()! as any, 'newMessage'),
133
+ waitForEvent3(subscriber.stack.getStreamrNode() as any, 'newMessage'),
134
134
  publisher.broadcast(response)
135
135
  ])
136
136
  })
@@ -33,8 +33,8 @@ describe('Full node network with WebRTC connections', () => {
33
33
  }
34
34
  })
35
35
  await entryPoint.start()
36
- entryPoint.getStreamrNode()!.setStreamPartEntryPoints(streamPartId, [epPeerDescriptor])
37
- entryPoint.getStreamrNode()!.joinStreamPart(streamPartId)
36
+ entryPoint.getStreamrNode().setStreamPartEntryPoints(streamPartId, [epPeerDescriptor])
37
+ entryPoint.getStreamrNode().joinStreamPart(streamPartId)
38
38
 
39
39
  await Promise.all(range(NUM_OF_NODES).map(async () => {
40
40
  const peerDescriptor = createMockPeerDescriptor()
@@ -62,15 +62,15 @@ describe('Full node network with WebRTC connections', () => {
62
62
  it('happy path', async () => {
63
63
  await Promise.all(nodes.map((node) =>
64
64
  waitForCondition(() => {
65
- return node.getStreamrNode()!.getNeighbors(streamPartId).length >= 3
65
+ return node.getStreamrNode().getNeighbors(streamPartId).length >= 3
66
66
  }
67
67
  , 30000)
68
68
  ))
69
69
  let receivedMessageCount = 0
70
70
  const successIds: string[] = []
71
71
  nodes.forEach((node) => {
72
- node.getStreamrNode()!.on('newMessage', () => {
73
- successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode()!.getPeerDescriptor()))
72
+ node.getStreamrNode().on('newMessage', () => {
73
+ successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode().getPeerDescriptor()))
74
74
  receivedMessageCount += 1
75
75
  })
76
76
  })
@@ -79,7 +79,7 @@ describe('Full node network with WebRTC connections', () => {
79
79
  streamPartId,
80
80
  randomEthereumAddress()
81
81
  )
82
- entryPoint.getStreamrNode()!.broadcast(msg)
82
+ entryPoint.getStreamrNode().broadcast(msg)
83
83
  await waitForCondition(() => receivedMessageCount === NUM_OF_NODES)
84
84
  }, 120000)
85
85
 
@@ -30,8 +30,8 @@ describe('Full node network with WebSocket connections only', () => {
30
30
  }
31
31
  })
32
32
  await entryPoint.start()
33
- entryPoint.getStreamrNode()!.setStreamPartEntryPoints(streamPartId, [epPeerDescriptor])
34
- entryPoint.getStreamrNode()!.joinStreamPart(streamPartId)
33
+ entryPoint.getStreamrNode().setStreamPartEntryPoints(streamPartId, [epPeerDescriptor])
34
+ entryPoint.getStreamrNode().joinStreamPart(streamPartId)
35
35
 
36
36
  await Promise.all(range(NUM_OF_NODES).map(async (i) => {
37
37
  const node = new NetworkStack({
@@ -60,15 +60,15 @@ describe('Full node network with WebSocket connections only', () => {
60
60
  it('happy path', async () => {
61
61
  await Promise.all(nodes.map((node) =>
62
62
  waitForCondition(() => {
63
- return node.getStreamrNode()!.getNeighbors(streamPartId).length >= 4
63
+ return node.getStreamrNode().getNeighbors(streamPartId).length >= 4
64
64
  }
65
65
  , 30000)
66
66
  ))
67
67
  let receivedMessageCount = 0
68
68
  const successIds: string[] = []
69
69
  nodes.forEach((node) => {
70
- node.getStreamrNode()!.on('newMessage', () => {
71
- successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode()!.getPeerDescriptor()))
70
+ node.getStreamrNode().on('newMessage', () => {
71
+ successIds.push(getNodeIdFromPeerDescriptor(node.getStreamrNode().getPeerDescriptor()))
72
72
  receivedMessageCount += 1
73
73
  })
74
74
  })
@@ -78,7 +78,7 @@ describe('Full node network with WebSocket connections only', () => {
78
78
  streamPartId,
79
79
  randomEthereumAddress()
80
80
  )
81
- entryPoint.getStreamrNode()!.broadcast(msg)
81
+ entryPoint.getStreamrNode().broadcast(msg)
82
82
  await waitForCondition(() => receivedMessageCount === NUM_OF_NODES)
83
83
  }, 220000)
84
84
 
@@ -92,7 +92,8 @@ describe('Handshakes', () => {
92
92
  neighbors,
93
93
  connectionLocker: mockConnectionLocker,
94
94
  rpcCommunicator: rpcCommunicator2,
95
- maxNeighborCount: 4
95
+ maxNeighborCount: 4,
96
+ ongoingHandshakes: new Set()
96
97
  })
97
98
 
98
99
  })
@@ -34,9 +34,9 @@ describe('NetworkStack', () => {
34
34
  })
35
35
 
36
36
  await stack1.start()
37
- stack1.getStreamrNode()!.setStreamPartEntryPoints(STREAM_PART_ID, [epDescriptor])
37
+ stack1.getStreamrNode().setStreamPartEntryPoints(STREAM_PART_ID, [epDescriptor])
38
38
  await stack2.start()
39
- stack2.getStreamrNode()!.setStreamPartEntryPoints(STREAM_PART_ID, [epDescriptor])
39
+ stack2.getStreamrNode().setStreamPartEntryPoints(STREAM_PART_ID, [epDescriptor])
40
40
  })
41
41
 
42
42
  afterEach(async () => {
@@ -95,7 +95,8 @@ describe('NetworkStack NodeInfoRpc', () => {
95
95
  controlLayerNeighbors: [normalizePeerDescriptor(otherPeerDescriptor)],
96
96
  deliveryLayerNeighbors: [normalizePeerDescriptor(otherPeerDescriptor)]
97
97
  }
98
- ]
98
+ ],
99
+ version: expect.any(String)
99
100
  })
100
101
  expect(result.streamPartitions.length).toEqual(2)
101
102
  })
@@ -15,7 +15,7 @@ describe('GroupKeyResponseTranslator', () => {
15
15
  })
16
16
  const newGroupKey: GroupKey = {
17
17
  id: 'id',
18
- data: hexToBinary('0000')!
18
+ data: hexToBinary('0000')
19
19
  }
20
20
  const newGroupKeyResponse: GroupKeyResponse = {
21
21
  requestId: 'request',
@@ -40,7 +40,8 @@ describe('Handshaker', () => {
40
40
  randomNodeView,
41
41
  rpcCommunicator,
42
42
  maxNeighborCount,
43
- rpcRequestTimeout: 5000
43
+ rpcRequestTimeout: 5000,
44
+ ongoingHandshakes: new Set()
44
45
  })
45
46
  })
46
47
 
@@ -1,4 +1,4 @@
1
- import { ListeningRpcCommunicator, getNodeIdFromPeerDescriptor } from '@streamr/dht'
1
+ import { DhtAddress, ListeningRpcCommunicator, getNodeIdFromPeerDescriptor } from '@streamr/dht'
2
2
  import { NeighborFinder } from '../../src/logic/neighbor-discovery/NeighborFinder'
3
3
  import { NeighborUpdateRpcLocal } from '../../src/logic/neighbor-discovery/NeighborUpdateRpcLocal'
4
4
  import { createMockPeerDescriptor } from '../utils/utils'
@@ -20,6 +20,7 @@ describe('NeighborUpdateRpcLocal', () => {
20
20
  let nearbyNodeView: NodeList
21
21
  let neighborFinder: NeighborFinder
22
22
  let rpcCommunicator: ListeningRpcCommunicator
23
+ let ongoingHandshakes: Set<DhtAddress>
23
24
 
24
25
  const addNeighbors = (count: number) => {
25
26
  for (let i = 0; i < count; i++) {
@@ -42,6 +43,7 @@ describe('NeighborUpdateRpcLocal', () => {
42
43
  const connectionLocker = {
43
44
  unlockConnection: jest.fn()
44
45
  } as any
46
+ ongoingHandshakes = new Set()
45
47
 
46
48
  rpcLocal = new NeighborUpdateRpcLocal({
47
49
  localPeerDescriptor,
@@ -51,7 +53,8 @@ describe('NeighborUpdateRpcLocal', () => {
51
53
  streamPartId,
52
54
  rpcCommunicator,
53
55
  neighborTargetCount,
54
- connectionLocker
56
+ connectionLocker,
57
+ ongoingHandshakes
55
58
  })
56
59
  })
57
60
 
@@ -126,4 +129,15 @@ describe('NeighborUpdateRpcLocal', () => {
126
129
  expect(neighbors.has(getNodeIdFromPeerDescriptor(caller))).toEqual(false)
127
130
  })
128
131
 
132
+ it('does not ask to be removed if there is an ongoing handshake to the caller', async () => {
133
+ const caller = createMockPeerDescriptor()
134
+ ongoingHandshakes.add(getNodeIdFromPeerDescriptor(caller))
135
+ const res = await rpcLocal.neighborUpdate({
136
+ streamPartId,
137
+ neighborDescriptors: [localPeerDescriptor],
138
+ removeMe: false
139
+ }, { incomingSourceDescriptor: caller } as any)
140
+ expect(res.removeMe).toEqual(false)
141
+ })
142
+
129
143
  })
@@ -6,7 +6,8 @@
6
6
  },
7
7
  "include": [
8
8
  "src/**/*",
9
- "test/**/*"
9
+ "test/**/*",
10
+ "package.json"
10
11
  ],
11
12
  "references": [
12
13
  { "path": "../protocol/tsconfig.node.json" },