@streamr/trackerless-network 101.0.0-beta.2 → 101.0.0-beta.3
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.
- package/dist/package.json +5 -6
- package/dist/src/NetworkNode.d.ts +5 -7
- package/dist/src/NetworkNode.js +5 -24
- package/dist/src/NetworkNode.js.map +1 -1
- package/dist/src/NetworkStack.d.ts +1 -2
- package/dist/src/NetworkStack.js +1 -2
- package/dist/src/NetworkStack.js.map +1 -1
- package/dist/src/exports.d.ts +3 -5
- package/dist/src/exports.js +13 -13
- package/dist/src/exports.js.map +1 -1
- package/dist/src/logic/ContentDeliveryLayerNode.d.ts +5 -5
- package/dist/src/logic/ContentDeliveryLayerNode.js +3 -3
- package/dist/src/logic/ContentDeliveryLayerNode.js.map +1 -1
- package/dist/src/logic/ContentDeliveryManager.d.ts +1 -2
- package/dist/src/logic/ContentDeliveryManager.js +2 -3
- package/dist/src/logic/ContentDeliveryManager.js.map +1 -1
- package/dist/src/logic/ContentDeliveryRpcLocal.d.ts +3 -3
- package/dist/src/logic/ContentDeliveryRpcLocal.js.map +1 -1
- package/dist/src/logic/ContentDeliveryRpcRemote.d.ts +1 -1
- package/dist/src/logic/ContentDeliveryRpcRemote.js.map +1 -1
- package/dist/src/logic/createContentDeliveryLayerNode.d.ts +1 -1
- package/dist/src/logic/formStreamPartDeliveryServiceId.d.ts +1 -1
- package/dist/src/logic/inspect/Inspector.d.ts +2 -2
- package/dist/src/logic/inspect/Inspector.js +2 -2
- package/dist/src/logic/inspect/Inspector.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.d.ts +4 -4
- package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.d.ts +1 -1
- package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +2 -2
- package/dist/src/logic/neighbor-discovery/Handshaker.js +4 -4
- package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +2 -2
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +3 -3
- package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.d.ts +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.d.ts +1 -1
- package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.js.map +1 -1
- package/dist/src/logic/proxy/ProxyClient.d.ts +1 -2
- package/dist/src/logic/proxy/ProxyClient.js +3 -3
- package/dist/src/logic/proxy/ProxyClient.js.map +1 -1
- package/dist/src/logic/proxy/ProxyConnectionRpcLocal.d.ts +3 -4
- package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js +4 -4
- package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js.map +1 -1
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.d.ts +4 -4
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js +1 -1
- package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js.map +1 -1
- package/dist/test/benchmark/first-message.js +23 -12
- package/dist/test/benchmark/first-message.js.map +1 -1
- package/dist/test/utils/utils.d.ts +4 -5
- package/dist/test/utils/utils.js +6 -7
- package/dist/test/utils/utils.js.map +1 -1
- package/package.json +5 -6
- package/src/NetworkNode.ts +7 -25
- package/src/NetworkStack.ts +1 -2
- package/src/exports.ts +14 -11
- package/src/logic/ContentDeliveryLayerNode.ts +13 -14
- package/src/logic/ContentDeliveryManager.ts +1 -2
- package/src/logic/ContentDeliveryRpcLocal.ts +3 -3
- package/src/logic/ContentDeliveryRpcRemote.ts +1 -2
- package/src/logic/createContentDeliveryLayerNode.ts +1 -1
- package/src/logic/formStreamPartDeliveryServiceId.ts +1 -1
- package/src/logic/inspect/Inspector.ts +3 -4
- package/src/logic/neighbor-discovery/HandshakeRpcLocal.ts +9 -10
- package/src/logic/neighbor-discovery/HandshakeRpcRemote.ts +1 -2
- package/src/logic/neighbor-discovery/Handshaker.ts +8 -9
- package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +4 -5
- package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +2 -2
- package/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.ts +1 -2
- package/src/logic/proxy/ProxyClient.ts +4 -5
- package/src/logic/proxy/ProxyConnectionRpcLocal.ts +5 -6
- package/src/logic/temporary-connection/TemporaryConnectionRpcLocal.ts +7 -7
- package/test/benchmark/StreamPartIdDataKeyDistribution.test.ts +2 -2
- package/test/benchmark/first-message.ts +28 -29
- package/test/end-to-end/content-delivery-layer-node-with-real-connections.test.ts +4 -5
- package/test/end-to-end/inspect.test.ts +26 -28
- package/test/end-to-end/proxy-and-full-node.test.ts +34 -32
- package/test/end-to-end/proxy-connections.test.ts +34 -31
- package/test/end-to-end/proxy-key-exchange.test.ts +41 -57
- package/test/end-to-end/webrtc-full-node-network.test.ts +1 -2
- package/test/end-to-end/websocket-full-node-network.test.ts +2 -3
- package/test/integration/ContentDeliveryLayerNode-Layer1Node-Latencies.test.ts +2 -3
- package/test/integration/ContentDeliveryLayerNode-Layer1Node.test.ts +2 -3
- package/test/integration/ContentDeliveryManager.test.ts +3 -4
- package/test/integration/ContentDeliveryRpcRemote.test.ts +7 -8
- package/test/integration/HandshakeRpcRemote.test.ts +6 -6
- package/test/integration/Handshakes.test.ts +6 -6
- package/test/integration/Inspect.test.ts +1 -1
- package/test/integration/NeighborUpdateRpcRemote.test.ts +1 -1
- package/test/integration/NetworkNode.test.ts +28 -29
- package/test/integration/NetworkRpc.test.ts +7 -8
- package/test/integration/NetworkStack.test.ts +4 -4
- package/test/integration/NodeInfoRpc.test.ts +3 -4
- package/test/integration/Propagation.test.ts +2 -3
- package/test/integration/joining-streams-on-offline-peers.test.ts +3 -4
- package/test/integration/stream-without-default-entrypoints.test.ts +26 -28
- package/test/integration/streamEntryPointReplacing.test.ts +5 -6
- package/test/unit/ContentDeliveryLayerNode.test.ts +5 -6
- package/test/unit/ContentDeliveryManager.test.ts +2 -3
- package/test/unit/ContentDeliveryRpcLocal.test.ts +1 -1
- package/test/unit/HandshakeRpcLocal.test.ts +2 -2
- package/test/unit/Handshaker.test.ts +2 -2
- package/test/unit/Inspector.test.ts +1 -2
- package/test/unit/NeighborUpdateRpcLocal.test.ts +6 -6
- package/test/unit/NetworkNode.test.ts +3 -4
- package/test/unit/NodeList.test.ts +2 -2
- package/test/unit/StreamPartIDDataKey.test.ts +1 -1
- package/test/unit/StreamPartNetworkSplitAvoidance.test.ts +1 -2
- package/test/unit/TemporaryConnectionRpcLocal.test.ts +2 -2
- package/test/utils/mock/MockTransport.ts +1 -2
- package/test/utils/utils.ts +8 -9
- package/tsconfig.jest.json +0 -1
- package/tsconfig.node.json +0 -2
- package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.d.ts +0 -6
- package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js +0 -28
- package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js.map +0 -1
- package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.d.ts +0 -6
- package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js +0 -32
- package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js.map +0 -1
- package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.d.ts +0 -6
- package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js +0 -170
- package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js.map +0 -1
- package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.d.ts +0 -7
- package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.js +0 -32
- package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.js.map +0 -1
- package/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.ts +0 -28
- package/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.ts +0 -34
- package/src/logic/protocol-integration/stream-message/StreamMessageTranslator.ts +0 -197
- package/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.ts +0 -37
- package/test/unit/GroupKeyResponseTranslator.test.ts +0 -39
- package/test/unit/StreamMessageTranslator.test.ts +0 -71
- package/test/unit/oldStreamMessageBinaryUtils.test.ts +0 -39
|
@@ -1,43 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ContentType,
|
|
3
|
-
EncryptionType,
|
|
4
|
-
MessageID,
|
|
5
|
-
MessageRef,
|
|
6
|
-
SignatureType,
|
|
7
|
-
StreamMessage,
|
|
8
|
-
StreamMessageType,
|
|
9
|
-
StreamPartIDUtils
|
|
10
|
-
} from '@streamr/protocol'
|
|
1
|
+
import { DhtAddress } from '@streamr/dht'
|
|
11
2
|
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
12
|
-
import { hexToBinary, utf8ToBinary, wait, waitForCondition, waitForEvent3 } from '@streamr/utils'
|
|
3
|
+
import { StreamPartIDUtils, hexToBinary, utf8ToBinary, wait, waitForCondition, waitForEvent3 } from '@streamr/utils'
|
|
13
4
|
import { NetworkNode, createNetworkNode } from '../../src/NetworkNode'
|
|
14
5
|
import { ContentDeliveryLayerNode } from '../../src/logic/ContentDeliveryLayerNode'
|
|
15
6
|
import { ProxyClient } from '../../src/logic/proxy/ProxyClient'
|
|
16
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
ContentType,
|
|
9
|
+
EncryptionType,
|
|
10
|
+
ProxyDirection,
|
|
11
|
+
SignatureType,
|
|
12
|
+
StreamMessage
|
|
13
|
+
} from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
17
14
|
import { createMockPeerDescriptor } from '../utils/utils'
|
|
18
|
-
import { DhtAddress } from '@streamr/dht'
|
|
19
15
|
|
|
20
16
|
const PROXIED_NODE_USER_ID = randomEthereumAddress()
|
|
21
17
|
const STREAM_PART_ID = StreamPartIDUtils.parse('proxy-test#0')
|
|
22
|
-
const MESSAGE =
|
|
23
|
-
messageId:
|
|
24
|
-
StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
25
|
-
StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
26
|
-
666,
|
|
27
|
-
0,
|
|
28
|
-
randomEthereumAddress(),
|
|
29
|
-
'msgChainId'
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
const MESSAGE: StreamMessage = {
|
|
19
|
+
messageId: {
|
|
20
|
+
streamId: StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
21
|
+
streamPartition: StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
22
|
+
timestamp: 666,
|
|
23
|
+
sequenceNumber: 0,
|
|
24
|
+
publisherId: hexToBinary(randomEthereumAddress()),
|
|
25
|
+
messageChainId: 'msgChainId'
|
|
26
|
+
},
|
|
27
|
+
previousMessageRef: {
|
|
28
|
+
timestamp: 665,
|
|
29
|
+
sequenceNumber: 0
|
|
30
|
+
},
|
|
31
|
+
body: {
|
|
32
|
+
oneofKind: 'contentMessage',
|
|
33
|
+
contentMessage: {
|
|
34
|
+
content: utf8ToBinary(JSON.stringify({
|
|
35
|
+
hello: 'world'
|
|
36
|
+
})),
|
|
37
|
+
contentType: ContentType.JSON,
|
|
38
|
+
encryptionType: EncryptionType.NONE,
|
|
39
|
+
}
|
|
40
|
+
},
|
|
37
41
|
signatureType: SignatureType.SECP256K1,
|
|
38
|
-
signature: hexToBinary('0x1234')
|
|
39
|
-
|
|
40
|
-
})
|
|
42
|
+
signature: hexToBinary('0x1234')
|
|
43
|
+
}
|
|
41
44
|
|
|
42
45
|
describe('Proxy connections', () => {
|
|
43
46
|
|
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
GroupKeyRequest as OldGroupKeyRequest,
|
|
6
|
-
GroupKeyResponse as OldGroupKeyResponse,
|
|
7
|
-
SignatureType,
|
|
8
|
-
StreamMessage,
|
|
9
|
-
StreamMessageType,
|
|
10
|
-
StreamPartIDUtils
|
|
11
|
-
} from '@streamr/protocol'
|
|
12
|
-
import { hexToBinary, toEthereumAddress, waitForEvent3 } from '@streamr/utils'
|
|
2
|
+
StreamPartIDUtils,
|
|
3
|
+
hexToBinary, toEthereumAddress, waitForEvent3
|
|
4
|
+
} from '@streamr/utils'
|
|
13
5
|
import { NetworkNode, createNetworkNode } from '../../src/NetworkNode'
|
|
14
|
-
import {
|
|
15
|
-
convertGroupKeyRequestToBytes,
|
|
16
|
-
convertGroupKeyResponseToBytes
|
|
17
|
-
} from '../../src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils'
|
|
18
|
-
import { ProxyDirection } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
6
|
+
import { ProxyDirection, SignatureType, StreamMessage } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
19
7
|
import { createMockPeerDescriptor } from '../utils/utils'
|
|
20
8
|
|
|
21
9
|
const STREAM_PART_ID = StreamPartIDUtils.parse('proxy-test#0')
|
|
@@ -75,30 +63,27 @@ describe('proxy group key exchange', () => {
|
|
|
75
63
|
await publisher.setProxies(STREAM_PART_ID, [proxyNodeDescriptor], ProxyDirection.PUBLISH, publisherUserId)
|
|
76
64
|
await subscriber.setProxies(STREAM_PART_ID, [proxyNodeDescriptor], ProxyDirection.SUBSCRIBE, subscriberUserId)
|
|
77
65
|
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
contentType: ContentType.BINARY,
|
|
97
|
-
encryptionType: EncryptionType.NONE,
|
|
98
|
-
content: convertGroupKeyRequestToBytes(groupKeyRequest),
|
|
66
|
+
const request: StreamMessage = {
|
|
67
|
+
messageId: {
|
|
68
|
+
streamId: StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
69
|
+
streamPartition: StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
70
|
+
timestamp: Date.now(),
|
|
71
|
+
sequenceNumber: 0,
|
|
72
|
+
publisherId: hexToBinary(subscriberUserId),
|
|
73
|
+
messageChainId: '0'
|
|
74
|
+
},
|
|
75
|
+
body: {
|
|
76
|
+
oneofKind: 'groupKeyRequest' as const,
|
|
77
|
+
groupKeyRequest: {
|
|
78
|
+
requestId: 'requestId',
|
|
79
|
+
recipientId: hexToBinary(publisherUserId),
|
|
80
|
+
rsaPublicKey: new Uint8Array(),
|
|
81
|
+
groupKeyIds: ['mock']
|
|
82
|
+
}
|
|
83
|
+
},
|
|
99
84
|
signatureType: SignatureType.SECP256K1,
|
|
100
85
|
signature: hexToBinary('1234')
|
|
101
|
-
}
|
|
86
|
+
}
|
|
102
87
|
|
|
103
88
|
await Promise.all([
|
|
104
89
|
waitForEvent3(publisher.stack.getContentDeliveryManager() as any, 'newMessage'),
|
|
@@ -110,27 +95,26 @@ describe('proxy group key exchange', () => {
|
|
|
110
95
|
await publisher.setProxies(STREAM_PART_ID, [proxyNodeDescriptor], ProxyDirection.PUBLISH, publisherUserId)
|
|
111
96
|
await subscriber.setProxies(STREAM_PART_ID, [proxyNodeDescriptor], ProxyDirection.SUBSCRIBE, subscriberUserId)
|
|
112
97
|
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
content: convertGroupKeyResponseToBytes(groupKeyResponse),
|
|
98
|
+
const response: StreamMessage = {
|
|
99
|
+
messageId: {
|
|
100
|
+
streamId: StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
101
|
+
streamPartition: StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
102
|
+
timestamp: Date.now(),
|
|
103
|
+
sequenceNumber: 0,
|
|
104
|
+
publisherId: hexToBinary(publisherUserId),
|
|
105
|
+
messageChainId: '0'
|
|
106
|
+
},
|
|
107
|
+
body: {
|
|
108
|
+
oneofKind: 'groupKeyResponse' as const,
|
|
109
|
+
groupKeyResponse: {
|
|
110
|
+
requestId: 'requestId',
|
|
111
|
+
recipientId: hexToBinary(publisherUserId),
|
|
112
|
+
groupKeys: []
|
|
113
|
+
}
|
|
114
|
+
},
|
|
131
115
|
signatureType: SignatureType.SECP256K1,
|
|
132
116
|
signature: hexToBinary('1234')
|
|
133
|
-
}
|
|
117
|
+
}
|
|
134
118
|
|
|
135
119
|
await Promise.all([
|
|
136
120
|
waitForEvent3(subscriber.stack.getContentDeliveryManager() as any, 'newMessage'),
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getNodeIdFromPeerDescriptor, getRandomRegion } from '@streamr/dht'
|
|
2
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
3
2
|
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
4
|
-
import { waitForCondition } from '@streamr/utils'
|
|
3
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
5
4
|
import { range } from 'lodash'
|
|
6
5
|
import { NetworkStack } from '../../src/NetworkStack'
|
|
7
6
|
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
2
2
|
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
3
|
-
import { waitForCondition } from '@streamr/utils'
|
|
3
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
4
4
|
import { range } from 'lodash'
|
|
5
5
|
import { NetworkStack } from '../../src/NetworkStack'
|
|
6
6
|
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
7
|
-
import { getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
8
7
|
|
|
9
8
|
describe('Full node network with WebSocket connections only', () => {
|
|
10
9
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { DhtNode, LatencyType, PeerDescriptor, Simulator, SimulatorTransport, getNodeIdFromPeerDescriptor } from '@streamr/dht'
|
|
2
|
-
import { waitForCondition } from '@streamr/utils'
|
|
2
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
3
3
|
import { range } from 'lodash'
|
|
4
4
|
import { ContentDeliveryLayerNode } from '../../src/logic/ContentDeliveryLayerNode'
|
|
5
|
+
import { DiscoveryLayerNode } from '../../src/logic/DiscoveryLayerNode'
|
|
5
6
|
import { createContentDeliveryLayerNode } from '../../src/logic/createContentDeliveryLayerNode'
|
|
6
7
|
import { createMockPeerDescriptor } from '../utils/utils'
|
|
7
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
8
|
-
import { DiscoveryLayerNode } from '../../src/logic/DiscoveryLayerNode'
|
|
9
8
|
|
|
10
9
|
describe('ContentDeliveryLayerNode-DhtNode-Latencies', () => {
|
|
11
10
|
const otherNodeCount = 64
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { ConnectionManager, DhtNode, PeerDescriptor, Simulator, SimulatorTransport, getNodeIdFromPeerDescriptor, getRandomRegion } from '@streamr/dht'
|
|
2
|
-
import { Logger, waitForCondition } from '@streamr/utils'
|
|
2
|
+
import { Logger, StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
3
3
|
import { range } from 'lodash'
|
|
4
4
|
import { ContentDeliveryLayerNode } from '../../src/logic/ContentDeliveryLayerNode'
|
|
5
|
+
import { DiscoveryLayerNode } from '../../src/logic/DiscoveryLayerNode'
|
|
5
6
|
import { createContentDeliveryLayerNode } from '../../src/logic/createContentDeliveryLayerNode'
|
|
6
7
|
import { createMockPeerDescriptor } from '../utils/utils'
|
|
7
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
8
|
-
import { DiscoveryLayerNode } from '../../src/logic/DiscoveryLayerNode'
|
|
9
8
|
|
|
10
9
|
const logger = new Logger(module)
|
|
11
10
|
|
|
@@ -3,12 +3,11 @@ import {
|
|
|
3
3
|
Simulator,
|
|
4
4
|
SimulatorTransport
|
|
5
5
|
} from '@streamr/dht'
|
|
6
|
-
import { ContentDeliveryManager, Events } from '../../src/logic/ContentDeliveryManager'
|
|
7
|
-
import { waitForEvent3, waitForCondition } from '@streamr/utils'
|
|
8
|
-
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
9
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
10
6
|
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
7
|
+
import { StreamPartIDUtils, waitForCondition, waitForEvent3 } from '@streamr/utils'
|
|
8
|
+
import { ContentDeliveryManager, Events } from '../../src/logic/ContentDeliveryManager'
|
|
11
9
|
import { ControlLayerNode } from '../../src/logic/ControlLayerNode'
|
|
10
|
+
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
12
11
|
|
|
13
12
|
describe('ContentDeliveryManager', () => {
|
|
14
13
|
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ListeningRpcCommunicator,
|
|
3
|
-
|
|
3
|
+
NodeType,
|
|
4
4
|
PeerDescriptor,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Simulator,
|
|
6
|
+
SimulatorTransport
|
|
7
7
|
} from '@streamr/dht'
|
|
8
|
+
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
9
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
8
10
|
import { ContentDeliveryRpcRemote } from '../../src/logic/ContentDeliveryRpcRemote'
|
|
9
|
-
import {
|
|
11
|
+
import { Empty } from '../../src/proto/google/protobuf/empty'
|
|
10
12
|
import {
|
|
11
13
|
LeaveStreamPartNotice,
|
|
12
14
|
StreamMessage
|
|
13
15
|
} from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
14
|
-
import {
|
|
15
|
-
import { waitForCondition } from '@streamr/utils'
|
|
16
|
+
import { ContentDeliveryRpcClient } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc.client'
|
|
16
17
|
import { createStreamMessage } from '../utils/utils'
|
|
17
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
18
|
-
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
19
18
|
|
|
20
19
|
describe('ContentDeliveryRpcRemote', () => {
|
|
21
20
|
let mockServerRpc: ListeningRpcCommunicator
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
StreamPartHandshakeRequest,
|
|
3
|
-
StreamPartHandshakeResponse
|
|
4
|
-
} from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
5
1
|
import {
|
|
6
2
|
ListeningRpcCommunicator,
|
|
7
3
|
NodeType,
|
|
@@ -9,11 +5,15 @@ import {
|
|
|
9
5
|
Simulator,
|
|
10
6
|
SimulatorTransport
|
|
11
7
|
} from '@streamr/dht'
|
|
8
|
+
import { StreamPartIDUtils } from '@streamr/utils'
|
|
9
|
+
import { HandshakeRpcRemote } from '../../src/logic/neighbor-discovery/HandshakeRpcRemote'
|
|
10
|
+
import {
|
|
11
|
+
StreamPartHandshakeRequest,
|
|
12
|
+
StreamPartHandshakeResponse
|
|
13
|
+
} from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
12
14
|
import {
|
|
13
15
|
HandshakeRpcClient,
|
|
14
16
|
} from '../../src/proto/packages/trackerless-network/protos/NetworkRpc.client'
|
|
15
|
-
import { HandshakeRpcRemote } from '../../src/logic/neighbor-discovery/HandshakeRpcRemote'
|
|
16
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
17
17
|
|
|
18
18
|
describe('HandshakeRpcRemote', () => {
|
|
19
19
|
let mockServerRpc: ListeningRpcCommunicator
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { Handshaker } from '../../src/logic/neighbor-discovery/Handshaker'
|
|
2
1
|
import {
|
|
2
|
+
ListeningRpcCommunicator,
|
|
3
3
|
NodeType,
|
|
4
4
|
PeerDescriptor,
|
|
5
|
-
ListeningRpcCommunicator,
|
|
6
5
|
Simulator,
|
|
7
6
|
SimulatorTransport,
|
|
8
7
|
getNodeIdFromPeerDescriptor
|
|
9
8
|
} from '@streamr/dht'
|
|
9
|
+
import { StreamPartIDUtils } from '@streamr/utils'
|
|
10
|
+
import { NodeList } from '../../src/logic/NodeList'
|
|
11
|
+
import { HandshakeRpcRemote } from '../../src/logic/neighbor-discovery/HandshakeRpcRemote'
|
|
12
|
+
import { Handshaker } from '../../src/logic/neighbor-discovery/Handshaker'
|
|
13
|
+
import { StreamPartHandshakeRequest, StreamPartHandshakeResponse } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
10
14
|
import {
|
|
11
15
|
HandshakeRpcClient
|
|
12
16
|
} from '../../src/proto/packages/trackerless-network/protos/NetworkRpc.client'
|
|
13
|
-
import { NodeList } from '../../src/logic/NodeList'
|
|
14
|
-
import { StreamPartHandshakeRequest, StreamPartHandshakeResponse } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
15
|
-
import { HandshakeRpcRemote } from '../../src/logic/neighbor-discovery/HandshakeRpcRemote'
|
|
16
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
17
17
|
|
|
18
18
|
describe('Handshakes', () => {
|
|
19
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LatencyType, PeerDescriptor, Simulator, SimulatorTransport } from '@streamr/dht'
|
|
2
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
3
2
|
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
3
|
+
import { StreamPartIDUtils } from '@streamr/utils'
|
|
4
4
|
import { range } from 'lodash'
|
|
5
5
|
import { NetworkStack } from '../../src/NetworkStack'
|
|
6
6
|
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
Simulator,
|
|
6
6
|
SimulatorTransport
|
|
7
7
|
} from '@streamr/dht'
|
|
8
|
+
import { StreamPartIDUtils } from '@streamr/utils'
|
|
8
9
|
import { NeighborUpdateRpcRemote } from '../../src/logic/neighbor-discovery/NeighborUpdateRpcRemote'
|
|
9
10
|
import { NeighborUpdate } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
10
11
|
import {
|
|
11
12
|
NeighborUpdateRpcClient,
|
|
12
13
|
} from '../../src/proto/packages/trackerless-network/protos/NetworkRpc.client'
|
|
13
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
14
14
|
|
|
15
15
|
describe('NeighborUpdateRpcRemote', () => {
|
|
16
16
|
let mockServerRpc: ListeningRpcCommunicator
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { PeerDescriptor, Simulator, SimulatorTransport } from '@streamr/dht'
|
|
2
|
-
import {
|
|
3
|
-
ContentType,
|
|
4
|
-
EncryptionType,
|
|
5
|
-
MessageID,
|
|
6
|
-
MessageRef, SignatureType,
|
|
7
|
-
StreamMessage,
|
|
8
|
-
StreamMessageType,
|
|
9
|
-
StreamPartIDUtils
|
|
10
|
-
} from '@streamr/protocol'
|
|
11
|
-
import { EthereumAddress, hexToBinary, utf8ToBinary, waitForCondition } from '@streamr/utils'
|
|
2
|
+
import { StreamPartIDUtils, hexToBinary, utf8ToBinary, waitForCondition } from '@streamr/utils'
|
|
12
3
|
import { NetworkNode, createNetworkNode } from '../../src/NetworkNode'
|
|
4
|
+
import { ContentType, EncryptionType, SignatureType, StreamMessage } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
13
5
|
import { createMockPeerDescriptor } from '../utils/utils'
|
|
14
6
|
|
|
15
7
|
const STREAM_PART_ID = StreamPartIDUtils.parse('test#0')
|
|
@@ -64,31 +56,38 @@ describe('NetworkNode', () => {
|
|
|
64
56
|
})
|
|
65
57
|
|
|
66
58
|
it('wait for join + broadcast and subscribe', async () => {
|
|
67
|
-
const streamMessage =
|
|
68
|
-
messageId:
|
|
69
|
-
StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
70
|
-
StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
71
|
-
666,
|
|
72
|
-
0,
|
|
73
|
-
'0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
|
74
|
-
'msgChainId'
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
59
|
+
const streamMessage: StreamMessage = {
|
|
60
|
+
messageId: {
|
|
61
|
+
streamId: StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
62
|
+
streamPartition: StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
63
|
+
timestamp: 666,
|
|
64
|
+
sequenceNumber: 0,
|
|
65
|
+
publisherId: hexToBinary('0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
66
|
+
messageChainId: 'msgChainId'
|
|
67
|
+
},
|
|
68
|
+
previousMessageRef: {
|
|
69
|
+
timestamp: 665,
|
|
70
|
+
sequenceNumber: 0
|
|
71
|
+
},
|
|
72
|
+
body: {
|
|
73
|
+
oneofKind: 'contentMessage',
|
|
74
|
+
contentMessage: {
|
|
75
|
+
content: utf8ToBinary(JSON.stringify({
|
|
76
|
+
hello: 'world'
|
|
77
|
+
})),
|
|
78
|
+
contentType: ContentType.JSON,
|
|
79
|
+
encryptionType: EncryptionType.NONE,
|
|
80
|
+
}
|
|
81
|
+
},
|
|
83
82
|
signatureType: SignatureType.SECP256K1,
|
|
84
83
|
signature: hexToBinary('0x1234'),
|
|
85
|
-
}
|
|
84
|
+
}
|
|
86
85
|
|
|
87
86
|
let msgCount = 0
|
|
88
87
|
await node1.join(STREAM_PART_ID)
|
|
89
88
|
node1.addMessageListener((msg) => {
|
|
90
|
-
expect(msg.messageId
|
|
91
|
-
expect(msg.
|
|
89
|
+
expect(msg.messageId!.timestamp).toEqual(666)
|
|
90
|
+
expect(msg.messageId!.sequenceNumber).toEqual(0)
|
|
92
91
|
msgCount += 1
|
|
93
92
|
})
|
|
94
93
|
await node2.broadcast(streamMessage)
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
+
import { DhtCallContext } from '@streamr/dht'
|
|
1
2
|
import {
|
|
2
|
-
RpcCommunicator,
|
|
3
3
|
ProtoRpcClient,
|
|
4
|
+
RpcCommunicator,
|
|
4
5
|
toProtoRpcClient
|
|
5
6
|
} from '@streamr/proto-rpc'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { waitForCondition } from '@streamr/utils'
|
|
7
|
+
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
8
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
9
9
|
import { Empty } from '../../src/proto/google/protobuf/empty'
|
|
10
|
-
import { createStreamMessage } from '../utils/utils'
|
|
11
10
|
import { RpcMessage } from '../../src/proto/packages/proto-rpc/protos/ProtoRpc'
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
11
|
+
import { StreamMessage } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
12
|
+
import { ContentDeliveryRpcClient } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc.client'
|
|
13
|
+
import { createStreamMessage } from '../utils/utils'
|
|
15
14
|
|
|
16
15
|
describe('Network RPC', () => {
|
|
17
16
|
let rpcCommunicator1: RpcCommunicator<DhtCallContext>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
StreamPartIDUtils
|
|
3
|
-
} from '@streamr/protocol'
|
|
4
1
|
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
5
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
StreamPartIDUtils,
|
|
4
|
+
waitForCondition
|
|
5
|
+
} from '@streamr/utils'
|
|
6
6
|
import { NetworkStack } from '../../src/NetworkStack'
|
|
7
7
|
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
8
8
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ListeningRpcCommunicator, PeerDescriptor, Simulator, SimulatorTransport } from '@streamr/dht'
|
|
2
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
2
3
|
import { NetworkStack } from '../../src/NetworkStack'
|
|
3
|
-
import { createMockPeerDescriptor } from '../utils/utils'
|
|
4
4
|
import { NodeInfoClient } from '../../src/logic/node-info/NodeInfoClient'
|
|
5
5
|
import { NODE_INFO_RPC_SERVICE_ID } from '../../src/logic/node-info/NodeInfoRpcLocal'
|
|
6
|
-
import {
|
|
7
|
-
import { waitForCondition } from '@streamr/utils'
|
|
6
|
+
import { createMockPeerDescriptor } from '../utils/utils'
|
|
8
7
|
|
|
9
8
|
// TODO add Jest utility so that the normalization is not needed (NET-1254)
|
|
10
9
|
const normalizePeerDescriptor = (peerDescriptor: PeerDescriptor) => {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Simulator } from '@streamr/dht'
|
|
2
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
3
2
|
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
4
|
-
import { waitForCondition } from '@streamr/utils'
|
|
3
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
5
4
|
import { range } from 'lodash'
|
|
6
5
|
import { ContentDeliveryLayerNode } from '../../src/logic/ContentDeliveryLayerNode'
|
|
7
|
-
import { createMockPeerDescriptor, createMockContentDeliveryLayerNodeAndDhtNode, createStreamMessage } from '../utils/utils'
|
|
8
6
|
import { DiscoveryLayerNode } from '../../src/logic/DiscoveryLayerNode'
|
|
7
|
+
import { createMockContentDeliveryLayerNodeAndDhtNode, createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
9
8
|
|
|
10
9
|
describe('Propagation', () => {
|
|
11
10
|
const entryPointDescriptor = createMockPeerDescriptor()
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { PeerDescriptor, Simulator, SimulatorTransport
|
|
1
|
+
import { LatencyType, PeerDescriptor, Simulator, SimulatorTransport } from '@streamr/dht'
|
|
2
|
+
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
3
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
2
4
|
import { NetworkStack } from '../../src/NetworkStack'
|
|
3
5
|
import { streamPartIdToDataKey } from '../../src/logic/ContentDeliveryManager'
|
|
4
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
5
6
|
import { Any } from '../../src/proto/google/protobuf/any'
|
|
6
7
|
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
7
|
-
import { waitForCondition } from '@streamr/utils'
|
|
8
|
-
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
9
8
|
|
|
10
9
|
const STREAM_PART_ID = StreamPartIDUtils.parse('stream#0')
|
|
11
10
|
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { LatencyType, PeerDescriptor, Simulator, SimulatorTransport } from '@streamr/dht'
|
|
2
|
-
import {
|
|
3
|
-
ContentType,
|
|
4
|
-
EncryptionType,
|
|
5
|
-
MessageID,
|
|
6
|
-
MessageRef,
|
|
7
|
-
SignatureType,
|
|
8
|
-
StreamMessage,
|
|
9
|
-
StreamMessageType,
|
|
10
|
-
StreamPartIDUtils
|
|
11
|
-
} from '@streamr/protocol'
|
|
12
|
-
import { EthereumAddress, hexToBinary, utf8ToBinary, waitForCondition } from '@streamr/utils'
|
|
2
|
+
import { StreamPartIDUtils, hexToBinary, utf8ToBinary, waitForCondition } from '@streamr/utils'
|
|
13
3
|
import { range } from 'lodash'
|
|
14
4
|
import { NetworkNode, createNetworkNode } from '../../src/NetworkNode'
|
|
15
5
|
import { streamPartIdToDataKey } from '../../src/logic/ContentDeliveryManager'
|
|
6
|
+
import { ContentType, EncryptionType, SignatureType, StreamMessage } from '../../src/proto/packages/trackerless-network/protos/NetworkRpc'
|
|
16
7
|
import { createMockPeerDescriptor } from '../utils/utils'
|
|
17
8
|
|
|
18
9
|
const STREAM_PART_ID = StreamPartIDUtils.parse('test#0')
|
|
@@ -24,25 +15,32 @@ describe('stream without default entrypoints', () => {
|
|
|
24
15
|
let receivedMessageCount: number
|
|
25
16
|
const entryPointPeerDescriptor: PeerDescriptor = createMockPeerDescriptor()
|
|
26
17
|
|
|
27
|
-
const streamMessage =
|
|
28
|
-
messageId:
|
|
29
|
-
StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
30
|
-
StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
31
|
-
666,
|
|
32
|
-
0,
|
|
33
|
-
'0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
|
|
34
|
-
'msgChainId'
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
18
|
+
const streamMessage: StreamMessage = {
|
|
19
|
+
messageId: {
|
|
20
|
+
streamId: StreamPartIDUtils.getStreamID(STREAM_PART_ID),
|
|
21
|
+
streamPartition: StreamPartIDUtils.getStreamPartition(STREAM_PART_ID),
|
|
22
|
+
timestamp: 666,
|
|
23
|
+
sequenceNumber: 0,
|
|
24
|
+
publisherId: hexToBinary('0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
|
|
25
|
+
messageChainId: 'msgChainId'
|
|
26
|
+
},
|
|
27
|
+
previousMessageRef: {
|
|
28
|
+
timestamp: 665,
|
|
29
|
+
sequenceNumber: 0
|
|
30
|
+
},
|
|
31
|
+
body: {
|
|
32
|
+
oneofKind: 'contentMessage',
|
|
33
|
+
contentMessage: {
|
|
34
|
+
content: utf8ToBinary(JSON.stringify({
|
|
35
|
+
hello: 'world'
|
|
36
|
+
})),
|
|
37
|
+
contentType: ContentType.JSON,
|
|
38
|
+
encryptionType: EncryptionType.NONE
|
|
39
|
+
}
|
|
40
|
+
},
|
|
43
41
|
signatureType: SignatureType.SECP256K1,
|
|
44
42
|
signature: hexToBinary('0x1234'),
|
|
45
|
-
}
|
|
43
|
+
}
|
|
46
44
|
|
|
47
45
|
beforeEach(async () => {
|
|
48
46
|
const simulator = new Simulator(LatencyType.REAL)
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { Simulator, SimulatorTransport
|
|
1
|
+
import { LatencyType, Simulator, SimulatorTransport } from '@streamr/dht'
|
|
2
|
+
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
3
|
+
import { StreamPartIDUtils, waitForCondition } from '@streamr/utils'
|
|
4
|
+
import { range } from 'lodash'
|
|
2
5
|
import { NetworkStack } from '../../src/NetworkStack'
|
|
3
|
-
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
4
6
|
import { MAX_NODE_COUNT } from '../../src/logic/PeerDescriptorStoreManager'
|
|
5
|
-
import {
|
|
6
|
-
import { StreamPartIDUtils } from '@streamr/protocol'
|
|
7
|
-
import { waitForCondition } from '@streamr/utils'
|
|
8
|
-
import { randomEthereumAddress } from '@streamr/test-utils'
|
|
7
|
+
import { createMockPeerDescriptor, createStreamMessage } from '../utils/utils'
|
|
9
8
|
|
|
10
9
|
describe('Stream Entry Points are replaced when known entry points leave streams', () => {
|
|
11
10
|
|