@streamr/trackerless-network 100.0.0-pretestnet.6 → 100.0.0-rc.1

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 (241) hide show
  1. package/README.md +57 -0
  2. package/dist/package.json +12 -12
  3. package/dist/src/NetworkNode.d.ts +6 -5
  4. package/dist/src/NetworkNode.js +9 -2
  5. package/dist/src/NetworkNode.js.map +1 -1
  6. package/dist/src/NetworkStack.d.ts +13 -9
  7. package/dist/src/NetworkStack.js +80 -12
  8. package/dist/src/NetworkStack.js.map +1 -1
  9. package/dist/src/exports.d.ts +4 -3
  10. package/dist/src/exports.js +12 -1
  11. package/dist/src/exports.js.map +1 -1
  12. package/dist/src/logic/DeliveryRpcLocal.d.ts +4 -5
  13. package/dist/src/logic/DeliveryRpcLocal.js +6 -5
  14. package/dist/src/logic/DeliveryRpcLocal.js.map +1 -1
  15. package/dist/src/logic/DeliveryRpcRemote.d.ts +5 -4
  16. package/dist/src/logic/DeliveryRpcRemote.js +4 -3
  17. package/dist/src/logic/DeliveryRpcRemote.js.map +1 -1
  18. package/dist/src/logic/DuplicateMessageDetector.d.ts +3 -3
  19. package/dist/src/logic/DuplicateMessageDetector.js +10 -6
  20. package/dist/src/logic/DuplicateMessageDetector.js.map +1 -1
  21. package/dist/src/logic/EntryPointDiscovery.d.ts +8 -5
  22. package/dist/src/logic/EntryPointDiscovery.js +24 -15
  23. package/dist/src/logic/EntryPointDiscovery.js.map +1 -1
  24. package/dist/src/logic/Layer0Node.d.ts +6 -4
  25. package/dist/src/logic/Layer1Node.d.ts +12 -6
  26. package/dist/src/logic/NodeList.d.ts +13 -15
  27. package/dist/src/logic/NodeList.js +19 -16
  28. package/dist/src/logic/NodeList.js.map +1 -1
  29. package/dist/src/logic/RandomGraphNode.d.ts +26 -22
  30. package/dist/src/logic/RandomGraphNode.js +85 -52
  31. package/dist/src/logic/RandomGraphNode.js.map +1 -1
  32. package/dist/src/logic/StreamrNode.d.ts +6 -6
  33. package/dist/src/logic/StreamrNode.js +53 -37
  34. package/dist/src/logic/StreamrNode.js.map +1 -1
  35. package/dist/src/logic/createRandomGraphNode.d.ts +2 -2
  36. package/dist/src/logic/createRandomGraphNode.js +33 -21
  37. package/dist/src/logic/createRandomGraphNode.js.map +1 -1
  38. package/dist/src/logic/formStreamPartDeliveryServiceId.d.ts +2 -1
  39. package/dist/src/logic/formStreamPartDeliveryServiceId.js.map +1 -1
  40. package/dist/src/logic/inspect/InspectSession.d.ts +4 -3
  41. package/dist/src/logic/inspect/InspectSession.js +6 -2
  42. package/dist/src/logic/inspect/InspectSession.js.map +1 -1
  43. package/dist/src/logic/inspect/Inspector.d.ts +11 -16
  44. package/dist/src/logic/inspect/Inspector.js +21 -9
  45. package/dist/src/logic/inspect/Inspector.js.map +1 -1
  46. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.d.ts +7 -9
  47. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.js +55 -32
  48. package/dist/src/logic/neighbor-discovery/HandshakeRpcLocal.js.map +1 -1
  49. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.d.ts +8 -6
  50. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.js +25 -16
  51. package/dist/src/logic/neighbor-discovery/HandshakeRpcRemote.js.map +1 -1
  52. package/dist/src/logic/neighbor-discovery/Handshaker.d.ts +9 -15
  53. package/dist/src/logic/neighbor-discovery/Handshaker.js +68 -44
  54. package/dist/src/logic/neighbor-discovery/Handshaker.js.map +1 -1
  55. package/dist/src/logic/neighbor-discovery/NeighborFinder.d.ts +8 -10
  56. package/dist/src/logic/neighbor-discovery/NeighborFinder.js +12 -2
  57. package/dist/src/logic/neighbor-discovery/NeighborFinder.js.map +1 -1
  58. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.d.ts +7 -10
  59. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js +11 -9
  60. package/dist/src/logic/neighbor-discovery/NeighborUpdateManager.js.map +1 -1
  61. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.d.ts +8 -4
  62. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js +33 -24
  63. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.js.map +1 -1
  64. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.d.ts +5 -4
  65. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.js +4 -5
  66. package/dist/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.js.map +1 -1
  67. package/dist/src/logic/node-info/NodeInfoClient.d.ts +9 -0
  68. package/dist/src/logic/node-info/NodeInfoClient.js +21 -0
  69. package/dist/src/logic/node-info/NodeInfoClient.js.map +1 -0
  70. package/dist/src/logic/node-info/NodeInfoRpcLocal.d.ts +12 -0
  71. package/dist/src/logic/node-info/NodeInfoRpcLocal.js +22 -0
  72. package/dist/src/logic/node-info/NodeInfoRpcLocal.js.map +1 -0
  73. package/dist/src/logic/node-info/NodeInfoRpcRemote.d.ts +6 -0
  74. package/dist/src/logic/node-info/NodeInfoRpcRemote.js +11 -0
  75. package/dist/src/logic/node-info/NodeInfoRpcRemote.js.map +1 -0
  76. package/dist/src/logic/propagation/FifoMapWithTTL.js +7 -3
  77. package/dist/src/logic/propagation/FifoMapWithTTL.js.map +1 -1
  78. package/dist/src/logic/propagation/Propagation.d.ts +4 -4
  79. package/dist/src/logic/propagation/Propagation.js +4 -0
  80. package/dist/src/logic/propagation/Propagation.js.map +1 -1
  81. package/dist/src/logic/propagation/PropagationTaskStore.d.ts +2 -2
  82. package/dist/src/logic/propagation/PropagationTaskStore.js +1 -0
  83. package/dist/src/logic/propagation/PropagationTaskStore.js.map +1 -1
  84. package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js +1 -1
  85. package/dist/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.js.map +1 -1
  86. package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js +1 -1
  87. package/dist/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.js.map +1 -1
  88. package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js +87 -53
  89. package/dist/src/logic/protocol-integration/stream-message/StreamMessageTranslator.js.map +1 -1
  90. package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.d.ts +7 -0
  91. package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.js +32 -0
  92. package/dist/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.js.map +1 -0
  93. package/dist/src/logic/proxy/ProxyClient.d.ts +8 -6
  94. package/dist/src/logic/proxy/ProxyClient.js +40 -28
  95. package/dist/src/logic/proxy/ProxyClient.js.map +1 -1
  96. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.d.ts +6 -7
  97. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js +8 -8
  98. package/dist/src/logic/proxy/ProxyConnectionRpcLocal.js.map +1 -1
  99. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.d.ts +3 -3
  100. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js +1 -1
  101. package/dist/src/logic/proxy/ProxyConnectionRpcRemote.js.map +1 -1
  102. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.d.ts +9 -4
  103. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js +21 -6
  104. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcLocal.js.map +1 -1
  105. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.d.ts +4 -3
  106. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.js +13 -3
  107. package/dist/src/logic/temporary-connection/TemporaryConnectionRpcRemote.js.map +1 -1
  108. package/dist/src/logic/utils.js.map +1 -1
  109. package/dist/src/proto/google/protobuf/any.js +8 -8
  110. package/dist/src/proto/google/protobuf/any.js.map +1 -1
  111. package/dist/src/proto/google/protobuf/empty.js +2 -4
  112. package/dist/src/proto/google/protobuf/empty.js.map +1 -1
  113. package/dist/src/proto/google/protobuf/timestamp.js +10 -10
  114. package/dist/src/proto/google/protobuf/timestamp.js.map +1 -1
  115. package/dist/src/proto/packages/dht/protos/DhtRpc.client.d.ts +36 -49
  116. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js +54 -52
  117. package/dist/src/proto/packages/dht/protos/DhtRpc.client.js.map +1 -1
  118. package/dist/src/proto/packages/dht/protos/DhtRpc.d.ts +184 -234
  119. package/dist/src/proto/packages/dht/protos/DhtRpc.js +118 -168
  120. package/dist/src/proto/packages/dht/protos/DhtRpc.js.map +1 -1
  121. package/dist/src/proto/packages/dht/protos/DhtRpc.server.d.ts +20 -29
  122. package/dist/src/proto/packages/proto-rpc/protos/ProtoRpc.js +1 -1
  123. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.d.ts +42 -5
  124. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js +52 -19
  125. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.client.js.map +1 -1
  126. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.d.ts +193 -28
  127. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js +129 -20
  128. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.js.map +1 -1
  129. package/dist/src/proto/packages/trackerless-network/protos/NetworkRpc.server.d.ts +20 -3
  130. package/dist/test/benchmark/first-message.js +14 -15
  131. package/dist/test/benchmark/first-message.js.map +1 -1
  132. package/dist/test/utils/utils.d.ts +2 -4
  133. package/dist/test/utils/utils.js +20 -19
  134. package/dist/test/utils/utils.js.map +1 -1
  135. package/jest.config.js +3 -38
  136. package/package.json +12 -12
  137. package/protos/NetworkRpc.proto +57 -12
  138. package/src/NetworkNode.ts +13 -6
  139. package/src/NetworkStack.ts +94 -16
  140. package/src/exports.ts +11 -3
  141. package/src/logic/DeliveryRpcLocal.ts +7 -8
  142. package/src/logic/DeliveryRpcRemote.ts +7 -5
  143. package/src/logic/DuplicateMessageDetector.ts +7 -7
  144. package/src/logic/EntryPointDiscovery.ts +26 -19
  145. package/src/logic/Layer0Node.ts +6 -4
  146. package/src/logic/Layer1Node.ts +21 -6
  147. package/src/logic/NodeList.ts +26 -27
  148. package/src/logic/RandomGraphNode.ts +158 -78
  149. package/src/logic/StreamrNode.ts +58 -41
  150. package/src/logic/createRandomGraphNode.ts +37 -25
  151. package/src/logic/formStreamPartDeliveryServiceId.ts +2 -1
  152. package/src/logic/inspect/InspectSession.ts +8 -4
  153. package/src/logic/inspect/Inspector.ts +34 -24
  154. package/src/logic/neighbor-discovery/HandshakeRpcLocal.ts +72 -38
  155. package/src/logic/neighbor-discovery/HandshakeRpcRemote.ts +32 -20
  156. package/src/logic/neighbor-discovery/Handshaker.ts +90 -75
  157. package/src/logic/neighbor-discovery/NeighborFinder.ts +18 -13
  158. package/src/logic/neighbor-discovery/NeighborUpdateManager.ts +19 -20
  159. package/src/logic/neighbor-discovery/NeighborUpdateRpcLocal.ts +43 -33
  160. package/src/logic/neighbor-discovery/NeighborUpdateRpcRemote.ts +6 -6
  161. package/src/logic/node-info/NodeInfoClient.ts +23 -0
  162. package/src/logic/node-info/NodeInfoRpcLocal.ts +28 -0
  163. package/src/logic/node-info/NodeInfoRpcRemote.ts +11 -0
  164. package/src/logic/propagation/Propagation.ts +7 -6
  165. package/src/logic/propagation/PropagationTaskStore.ts +2 -2
  166. package/src/logic/protocol-integration/stream-message/GroupKeyRequestTranslator.ts +1 -1
  167. package/src/logic/protocol-integration/stream-message/GroupKeyResponseTranslator.ts +1 -2
  168. package/src/logic/protocol-integration/stream-message/StreamMessageTranslator.ts +95 -69
  169. package/src/logic/protocol-integration/stream-message/oldStreamMessageBinaryUtils.ts +37 -0
  170. package/src/logic/proxy/ProxyClient.ts +60 -40
  171. package/src/logic/proxy/ProxyConnectionRpcLocal.ts +15 -19
  172. package/src/logic/proxy/ProxyConnectionRpcRemote.ts +3 -3
  173. package/src/logic/temporary-connection/TemporaryConnectionRpcLocal.ts +30 -10
  174. package/src/logic/temporary-connection/TemporaryConnectionRpcRemote.ts +14 -4
  175. package/src/proto/google/protobuf/any.ts +4 -4
  176. package/src/proto/google/protobuf/empty.ts +2 -4
  177. package/src/proto/google/protobuf/timestamp.ts +4 -4
  178. package/src/proto/packages/dht/protos/DhtRpc.client.ts +50 -66
  179. package/src/proto/packages/dht/protos/DhtRpc.server.ts +21 -30
  180. package/src/proto/packages/dht/protos/DhtRpc.ts +242 -316
  181. package/src/proto/packages/proto-rpc/protos/ProtoRpc.ts +1 -1
  182. package/src/proto/packages/trackerless-network/protos/NetworkRpc.client.ts +49 -7
  183. package/src/proto/packages/trackerless-network/protos/NetworkRpc.server.ts +21 -4
  184. package/src/proto/packages/trackerless-network/protos/NetworkRpc.ts +251 -44
  185. package/test/benchmark/StreamPartIdDataKeyDistribution.test.ts +60 -0
  186. package/test/benchmark/first-message.ts +38 -17
  187. package/test/end-to-end/inspect.test.ts +16 -4
  188. package/test/end-to-end/proxy-and-full-node.test.ts +26 -13
  189. package/test/end-to-end/proxy-connections.test.ts +23 -11
  190. package/test/end-to-end/proxy-key-exchange.test.ts +25 -15
  191. package/test/end-to-end/random-graph-with-real-connections.test.ts +35 -32
  192. package/test/end-to-end/webrtc-full-node-network.test.ts +11 -12
  193. package/test/end-to-end/websocket-full-node-network.test.ts +12 -12
  194. package/test/integration/DeliveryRpcRemote.test.ts +6 -9
  195. package/test/integration/HandshakeRpcRemote.test.ts +6 -8
  196. package/test/integration/Handshakes.test.ts +29 -27
  197. package/test/integration/Inspect.test.ts +0 -2
  198. package/test/integration/NeighborUpdateRpcRemote.test.ts +6 -7
  199. package/test/integration/NetworkNode.test.ts +27 -12
  200. package/test/integration/NetworkRpc.test.ts +3 -5
  201. package/test/integration/NetworkStack.test.ts +2 -2
  202. package/test/integration/NodeInfoRpc.test.ts +104 -0
  203. package/test/integration/Propagation.test.ts +3 -3
  204. package/test/integration/RandomGraphNode-Layer1Node-Latencies.test.ts +24 -25
  205. package/test/integration/RandomGraphNode-Layer1Node.test.ts +26 -24
  206. package/test/integration/StreamrNode.test.ts +4 -16
  207. package/test/integration/joining-streams-on-offline-peers.test.ts +7 -31
  208. package/test/integration/stream-without-default-entrypoints.test.ts +22 -23
  209. package/test/integration/streamEntryPointReplacing.test.ts +94 -0
  210. package/test/unit/DeliveryRpcLocal.test.ts +2 -1
  211. package/test/unit/EntrypointDiscovery.test.ts +11 -8
  212. package/test/unit/GroupKeyResponseTranslator.test.ts +1 -1
  213. package/test/unit/HandshakeRpcLocal.test.ts +80 -28
  214. package/test/unit/Handshaker.test.ts +14 -9
  215. package/test/unit/InspectSession.test.ts +5 -6
  216. package/test/unit/Inspector.test.ts +3 -4
  217. package/test/unit/NeighborFinder.test.ts +12 -9
  218. package/test/unit/NeighborUpdateRpcLocal.test.ts +139 -0
  219. package/test/unit/NodeList.test.ts +77 -80
  220. package/test/unit/Propagation.test.ts +21 -16
  221. package/test/unit/ProxyConnectionRpcRemote.test.ts +18 -12
  222. package/test/unit/RandomGraphNode.test.ts +23 -20
  223. package/test/unit/StreamMessageTranslator.test.ts +10 -8
  224. package/test/unit/StreamPartIDDataKey.test.ts +12 -0
  225. package/test/unit/StreamrNode.test.ts +2 -0
  226. package/test/unit/TemporaryConnectionRpcLocal.test.ts +38 -0
  227. package/test/unit/oldStreamMessageBinaryUtils.test.ts +39 -0
  228. package/test/utils/mock/MockHandshaker.ts +6 -5
  229. package/test/utils/mock/MockLayer0Node.ts +7 -2
  230. package/test/utils/mock/MockLayer1Node.ts +5 -2
  231. package/test/utils/mock/MockNeighborFinder.ts +3 -2
  232. package/test/utils/mock/MockNeighborUpdateManager.ts +3 -2
  233. package/test/utils/mock/Transport.ts +1 -1
  234. package/test/utils/utils.ts +40 -25
  235. package/tsconfig.jest.json +5 -4
  236. package/tsconfig.node.json +2 -2
  237. package/dist/src/identifiers.d.ts +0 -4
  238. package/dist/src/identifiers.js +0 -9
  239. package/dist/src/identifiers.js.map +0 -1
  240. package/src/identifiers.ts +0 -8
  241. package/test/unit/GroupKeyRequestTranslator.test.ts +0 -36
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  ConnectionLocker,
3
+ DhtAddress,
3
4
  ITransport,
4
5
  ListeningRpcCommunicator,
5
- PeerDescriptor
6
+ PeerDescriptor,
7
+ getNodeIdFromPeerDescriptor
6
8
  } from '@streamr/dht'
7
- import { toProtoRpcClient } from '@streamr/proto-rpc'
8
9
  import { StreamPartID } from '@streamr/protocol'
9
10
  import { EthereumAddress, Logger, addManagedEventListener, wait } from '@streamr/utils'
10
11
  import { EventEmitter } from 'eventemitter3'
11
12
  import { sampleSize } from 'lodash'
12
- import { NodeID, getNodeIdFromPeerDescriptor } from '../../identifiers'
13
13
  import {
14
14
  LeaveStreamPartNotice,
15
15
  MessageID,
@@ -27,6 +27,7 @@ import { markAndCheckDuplicate } from '../utils'
27
27
  import { ProxyConnectionRpcRemote } from './ProxyConnectionRpcRemote'
28
28
  import { formStreamPartDeliveryServiceId } from '../formStreamPartDeliveryServiceId'
29
29
 
30
+ // TODO use config option or named constant?
30
31
  export const retry = async <T>(task: () => Promise<T>, description: string, abortSignal: AbortSignal, delay = 10000): Promise<T> => {
31
32
  // eslint-disable-next-line no-constant-condition
32
33
  while (true) {
@@ -51,41 +52,52 @@ interface ProxyClientConfig {
51
52
  }
52
53
 
53
54
  interface ProxyDefinition {
54
- nodes: Map<NodeID, PeerDescriptor>
55
+ nodes: Map<DhtAddress, PeerDescriptor>
55
56
  connectionCount: number
56
57
  direction: ProxyDirection
57
58
  userId: EthereumAddress
58
59
  }
59
60
 
61
+ interface ProxyConnection {
62
+ peerDescriptor: PeerDescriptor
63
+ direction: ProxyDirection
64
+ }
65
+
66
+ interface Events {
67
+ message: (message: StreamMessage) => void
68
+ }
69
+
60
70
  const logger = new Logger(module)
61
71
 
62
72
  const SERVICE_ID = 'system/proxy-client'
63
73
 
64
- export class ProxyClient extends EventEmitter {
74
+ export class ProxyClient extends EventEmitter<Events> {
65
75
 
66
76
  private readonly rpcCommunicator: ListeningRpcCommunicator
67
77
  private readonly deliveryRpcLocal: DeliveryRpcLocal
68
78
  private readonly config: ProxyClientConfig
69
79
  private readonly duplicateDetectors: Map<string, DuplicateMessageDetector> = new Map()
70
80
  private definition?: ProxyDefinition
71
- private readonly connections: Map<NodeID, ProxyDirection> = new Map()
81
+ private readonly connections: Map<DhtAddress, ProxyConnection> = new Map()
72
82
  private readonly propagation: Propagation
73
- private readonly targetNeighbors: NodeList
83
+ private readonly neighbors: NodeList
74
84
  private readonly abortController: AbortController
75
85
 
76
86
  constructor(config: ProxyClientConfig) {
77
87
  super()
78
88
  this.config = config
79
89
  this.rpcCommunicator = new ListeningRpcCommunicator(formStreamPartDeliveryServiceId(config.streamPartId), config.transport)
80
- this.targetNeighbors = new NodeList(getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor), 1000)
90
+ // TODO use config option or named constant?
91
+ this.neighbors = new NodeList(getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor), 1000)
81
92
  this.deliveryRpcLocal = new DeliveryRpcLocal({
82
93
  localPeerDescriptor: this.config.localPeerDescriptor,
83
94
  streamPartId: this.config.streamPartId,
84
95
  markAndCheckDuplicate: (msg: MessageID, prev?: MessageRef) => markAndCheckDuplicate(this.duplicateDetectors, msg, prev),
85
- broadcast: (message: StreamMessage, previousNode?: NodeID) => this.broadcast(message, previousNode),
86
- onLeaveNotice: (senderId: NodeID) => {
87
- const contact = this.targetNeighbors.get(senderId)
96
+ broadcast: (message: StreamMessage, previousNode?: DhtAddress) => this.broadcast(message, previousNode),
97
+ onLeaveNotice: (senderId: DhtAddress) => {
98
+ const contact = this.neighbors.get(senderId)
88
99
  if (contact) {
100
+ // TODO should we catch possible promise rejection?
89
101
  setImmediate(() => this.onNodeDisconnected(contact.getPeerDescriptor()))
90
102
  }
91
103
  },
@@ -93,9 +105,10 @@ export class ProxyClient extends EventEmitter {
93
105
  markForInspection: () => {}
94
106
  })
95
107
  this.propagation = new Propagation({
108
+ // TODO use config option or named constant?
96
109
  minPropagationTargets: config.minPropagationTargets ?? 2,
97
- sendToNeighbor: async (neighborId: NodeID, msg: StreamMessage): Promise<void> => {
98
- const remote = this.targetNeighbors.get(neighborId)
110
+ sendToNeighbor: async (neighborId: DhtAddress, msg: StreamMessage): Promise<void> => {
111
+ const remote = this.neighbors.get(neighborId)
99
112
  if (remote) {
100
113
  await remote.sendStreamMessage(msg)
101
114
  } else {
@@ -121,9 +134,9 @@ export class ProxyClient extends EventEmitter {
121
134
  ): Promise<void> {
122
135
  logger.trace('Setting proxies', { streamPartId: this.config.streamPartId, peerDescriptors: nodes, direction, userId, connectionCount })
123
136
  if (connectionCount !== undefined && connectionCount > nodes.length) {
124
- throw Error('Cannot set connectionCount above the size of the configured array of nodes')
137
+ throw new Error('Cannot set connectionCount above the size of the configured array of nodes')
125
138
  }
126
- const nodesIds = new Map()
139
+ const nodesIds = new Map<DhtAddress, PeerDescriptor>()
127
140
  nodes.forEach((peerDescriptor) => {
128
141
  nodesIds.set(getNodeIdFromPeerDescriptor(peerDescriptor), peerDescriptor)
129
142
  })
@@ -148,37 +161,41 @@ export class ProxyClient extends EventEmitter {
148
161
  }
149
162
  }
150
163
 
151
- private getInvalidConnections(): NodeID[] {
164
+ private getInvalidConnections(): DhtAddress[] {
152
165
  return Array.from(this.connections.keys()).filter((id) => {
153
166
  return !this.definition!.nodes.has(id)
154
- || this.definition!.direction !== this.connections.get(id)
167
+ || this.definition!.direction !== this.connections.get(id)!.direction
155
168
  })
156
169
  }
157
170
 
158
171
  private async openRandomConnections(connectionCount: number): Promise<void> {
159
172
  const proxiesToAttempt = sampleSize(Array.from(this.definition!.nodes.keys()).filter((id) =>
160
- !this.connections.has(id as unknown as NodeID)
173
+ !this.connections.has(id)
161
174
  ), connectionCount)
162
175
  await Promise.all(proxiesToAttempt.map((id) =>
163
- this.attemptConnection(id as unknown as NodeID, this.definition!.direction, this.definition!.userId)
176
+ this.attemptConnection(id, this.definition!.direction, this.definition!.userId)
164
177
  ))
165
178
  }
166
179
 
167
- private async attemptConnection(nodeId: NodeID, direction: ProxyDirection, userId: EthereumAddress): Promise<void> {
180
+ private async attemptConnection(nodeId: DhtAddress, direction: ProxyDirection, userId: EthereumAddress): Promise<void> {
168
181
  const peerDescriptor = this.definition!.nodes.get(nodeId)!
169
- const client = toProtoRpcClient(new ProxyConnectionRpcClient(this.rpcCommunicator.getRpcClientTransport()))
170
- const rpcRemote = new ProxyConnectionRpcRemote(this.config.localPeerDescriptor, peerDescriptor, this.config.streamPartId, client)
182
+ const rpcRemote = new ProxyConnectionRpcRemote(
183
+ this.config.localPeerDescriptor,
184
+ peerDescriptor,
185
+ this.rpcCommunicator,
186
+ ProxyConnectionRpcClient
187
+ )
171
188
  const accepted = await rpcRemote.requestConnection(direction, userId)
172
189
  if (accepted) {
173
190
  this.config.connectionLocker.lockConnection(peerDescriptor, SERVICE_ID)
174
- this.connections.set(nodeId, direction)
191
+ this.connections.set(nodeId, { peerDescriptor, direction })
175
192
  const remote = new DeliveryRpcRemote(
176
193
  this.config.localPeerDescriptor,
177
194
  peerDescriptor,
178
- this.config.streamPartId,
179
- toProtoRpcClient(new DeliveryRpcClient(this.rpcCommunicator.getRpcClientTransport()))
195
+ this.rpcCommunicator,
196
+ DeliveryRpcClient
180
197
  )
181
- this.targetNeighbors.add(remote)
198
+ this.neighbors.add(remote)
182
199
  this.propagation.onNeighborJoined(nodeId)
183
200
  logger.info('Open proxy connection', {
184
201
  nodeId,
@@ -197,32 +214,34 @@ export class ProxyClient extends EventEmitter {
197
214
  await Promise.allSettled(proxiesToDisconnect.map((node) => this.closeConnection(node)))
198
215
  }
199
216
 
200
- private async closeConnection(nodeId: NodeID): Promise<void> {
217
+ private async closeConnection(nodeId: DhtAddress): Promise<void> {
201
218
  if (this.connections.has(nodeId)) {
202
219
  logger.info('Close proxy connection', {
203
220
  nodeId
204
221
  })
205
- const server = this.targetNeighbors.get(nodeId)
206
- server?.leaveStreamPartNotice()
207
- this.removeConnection(nodeId)
222
+ const server = this.neighbors.get(nodeId)
223
+ server?.leaveStreamPartNotice(this.config.streamPartId, false)
224
+ this.removeConnection(this.connections.get(nodeId)!.peerDescriptor)
208
225
  }
209
226
  }
210
227
 
211
- private removeConnection(nodeId: NodeID): void {
228
+ private removeConnection(peerDescriptor: PeerDescriptor): void {
229
+ const nodeId = getNodeIdFromPeerDescriptor(peerDescriptor)
212
230
  this.connections.delete(nodeId)
213
- this.targetNeighbors.removeById(nodeId)
231
+ this.neighbors.remove(nodeId)
232
+ this.config.connectionLocker.unlockConnection(peerDescriptor, SERVICE_ID)
214
233
  }
215
234
 
216
- broadcast(msg: StreamMessage, previousNode?: NodeID): void {
235
+ broadcast(msg: StreamMessage, previousNode?: DhtAddress): void {
217
236
  if (!previousNode) {
218
237
  markAndCheckDuplicate(this.duplicateDetectors, msg.messageId!, msg.previousMessageRef)
219
238
  }
220
239
  this.emit('message', msg)
221
- this.propagation.feedUnseenMessage(msg, this.targetNeighbors.getIds(), previousNode ?? null)
240
+ this.propagation.feedUnseenMessage(msg, this.neighbors.getIds(), previousNode ?? null)
222
241
  }
223
242
 
224
- hasConnection(nodeId: NodeID, direction: ProxyDirection): boolean {
225
- return this.connections.has(nodeId) && this.connections.get(nodeId) === direction
243
+ hasConnection(nodeId: DhtAddress, direction: ProxyDirection): boolean {
244
+ return this.connections.has(nodeId) && this.connections.get(nodeId)!.direction === direction
226
245
  }
227
246
 
228
247
  getDirection(): ProxyDirection {
@@ -233,7 +252,7 @@ export class ProxyClient extends EventEmitter {
233
252
  const nodeId = getNodeIdFromPeerDescriptor(peerDescriptor)
234
253
  if (this.connections.has(nodeId)) {
235
254
  this.config.connectionLocker.unlockConnection(peerDescriptor, SERVICE_ID)
236
- this.removeConnection(nodeId)
255
+ this.removeConnection(peerDescriptor)
237
256
  await retry(() => this.updateConnections(), 'updating proxy connections', this.abortController.signal)
238
257
  }
239
258
  }
@@ -243,17 +262,18 @@ export class ProxyClient extends EventEmitter {
243
262
  addManagedEventListener<any, any>(
244
263
  this.config.transport as any,
245
264
  'disconnected',
265
+ // TODO should we catch possible promise rejection?
246
266
  (peerDescriptor: PeerDescriptor) => this.onNodeDisconnected(peerDescriptor),
247
267
  this.abortController.signal
248
268
  )
249
269
  }
250
270
 
251
271
  stop(): void {
252
- this.targetNeighbors.getAll().map((remote) => {
272
+ this.neighbors.getAll().forEach((remote) => {
253
273
  this.config.connectionLocker.unlockConnection(remote.getPeerDescriptor(), SERVICE_ID)
254
- remote.leaveStreamPartNotice()
274
+ remote.leaveStreamPartNotice(this.config.streamPartId, false)
255
275
  })
256
- this.targetNeighbors.stop()
276
+ this.neighbors.stop()
257
277
  this.rpcCommunicator.destroy()
258
278
  this.connections.clear()
259
279
  this.abortController.abort()
@@ -1,21 +1,17 @@
1
1
  import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
2
  import {
3
- GroupKeyRequest,
4
3
  ProxyConnectionRequest,
5
4
  ProxyConnectionResponse,
6
5
  ProxyDirection,
7
- StreamMessage,
8
- StreamMessageType
6
+ StreamMessage
9
7
  } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
10
8
  import { IProxyConnectionRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
11
9
  import { DeliveryRpcRemote } from '../DeliveryRpcRemote'
12
- import { DhtCallContext, ListeningRpcCommunicator, PeerDescriptor } from '@streamr/dht'
13
- import { toProtoRpcClient } from '@streamr/proto-rpc'
10
+ import { DhtAddress, DhtCallContext, ListeningRpcCommunicator, PeerDescriptor, getNodeIdFromPeerDescriptor } from '@streamr/dht'
14
11
  import { DeliveryRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
15
12
  import { EventEmitter } from 'eventemitter3'
16
13
  import { EthereumAddress, Logger, binaryToHex, toEthereumAddress } from '@streamr/utils'
17
14
  import { StreamPartID } from '@streamr/protocol'
18
- import { NodeID, getNodeIdFromPeerDescriptor } from '../../identifiers'
19
15
 
20
16
  const logger = new Logger(module)
21
17
 
@@ -32,13 +28,13 @@ interface ProxyConnectionRpcLocalConfig {
32
28
  }
33
29
 
34
30
  export interface Events {
35
- newConnection: (nodeId: NodeID) => void
31
+ newConnection: (nodeId: DhtAddress) => void
36
32
  }
37
33
 
38
34
  export class ProxyConnectionRpcLocal extends EventEmitter<Events> implements IProxyConnectionRpc {
39
35
 
40
36
  private readonly config: ProxyConnectionRpcLocalConfig
41
- private readonly connections: Map<NodeID, ProxyConnection> = new Map()
37
+ private readonly connections: Map<DhtAddress, ProxyConnection> = new Map()
42
38
 
43
39
  constructor(config: ProxyConnectionRpcLocalConfig) {
44
40
  super()
@@ -47,28 +43,28 @@ export class ProxyConnectionRpcLocal extends EventEmitter<Events> implements IPr
47
43
  (msg: ProxyConnectionRequest, context) => this.requestConnection(msg, context))
48
44
  }
49
45
 
50
- getConnection(nodeId: NodeID): ProxyConnection | undefined {
46
+ getConnection(nodeId: DhtAddress): ProxyConnection | undefined {
51
47
  return this.connections.get(nodeId)
52
48
  }
53
49
 
54
- hasConnection(nodeId: NodeID): boolean {
50
+ hasConnection(nodeId: DhtAddress): boolean {
55
51
  return this.connections.has(nodeId)
56
52
  }
57
53
 
58
- removeConnection(nodeId: NodeID): void {
54
+ removeConnection(nodeId: DhtAddress): void {
59
55
  this.connections.delete(nodeId)
60
56
  }
61
57
 
62
58
  stop(): void {
63
- this.connections.forEach((connection) => connection.remote.leaveStreamPartNotice())
59
+ this.connections.forEach((connection) => connection.remote.leaveStreamPartNotice(this.config.streamPartId, false))
64
60
  this.connections.clear()
65
61
  this.removeAllListeners()
66
62
  }
67
63
 
68
- getPropagationTargets(msg: StreamMessage): NodeID[] {
69
- if (msg.messageType === StreamMessageType.GROUP_KEY_REQUEST) {
64
+ getPropagationTargets(msg: StreamMessage): DhtAddress[] {
65
+ if (msg.body.oneofKind === 'groupKeyRequest') {
70
66
  try {
71
- const recipientId = GroupKeyRequest.fromBinary(msg.content).recipientId
67
+ const recipientId = msg.body.groupKeyRequest.recipientId
72
68
  return this.getNodeIdsForUserId(toEthereumAddress(binaryToHex(recipientId, true)))
73
69
  } catch (err) {
74
70
  logger.trace(`Could not parse GroupKeyRequest: ${err}`)
@@ -79,11 +75,11 @@ export class ProxyConnectionRpcLocal extends EventEmitter<Events> implements IPr
79
75
  }
80
76
  }
81
77
 
82
- private getNodeIdsForUserId(userId: EthereumAddress): NodeID[] {
78
+ private getNodeIdsForUserId(userId: EthereumAddress): DhtAddress[] {
83
79
  return Array.from(this.connections.keys()).filter((nodeId) => this.connections.get(nodeId)!.userId === userId)
84
80
  }
85
81
 
86
- private getSubscribers(): NodeID[] {
82
+ private getSubscribers(): DhtAddress[] {
87
83
  return Array.from(this.connections.keys()).filter((key) => this.connections.get(key)!.direction === ProxyDirection.SUBSCRIBE)
88
84
  }
89
85
 
@@ -97,8 +93,8 @@ export class ProxyConnectionRpcLocal extends EventEmitter<Events> implements IPr
97
93
  remote: new DeliveryRpcRemote(
98
94
  this.config.localPeerDescriptor,
99
95
  senderPeerDescriptor,
100
- this.config.streamPartId,
101
- toProtoRpcClient(new DeliveryRpcClient(this.config.rpcCommunicator.getRpcClientTransport()))
96
+ this.config.rpcCommunicator,
97
+ DeliveryRpcClient
102
98
  )
103
99
  })
104
100
  const response: ProxyConnectionResponse = {
@@ -1,11 +1,11 @@
1
- import { Remote, EXISTING_CONNECTION_TIMEOUT } from '@streamr/dht'
1
+ import { EXISTING_CONNECTION_TIMEOUT, RpcRemote } from '@streamr/dht'
2
2
  import { EthereumAddress, Logger, hexToBinary } from '@streamr/utils'
3
3
  import { ProxyConnectionRequest, ProxyDirection } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
4
- import { IProxyConnectionRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
4
+ import { ProxyConnectionRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
5
5
 
6
6
  const logger = new Logger(module)
7
7
 
8
- export class ProxyConnectionRpcRemote extends Remote<IProxyConnectionRpcClient> {
8
+ export class ProxyConnectionRpcRemote extends RpcRemote<ProxyConnectionRpcClient> {
9
9
 
10
10
  async requestConnection(direction: ProxyDirection, userId: EthereumAddress): Promise<boolean> {
11
11
  const request: ProxyConnectionRequest = {
@@ -1,37 +1,50 @@
1
1
  import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
2
- import { TemporaryConnectionRequest, TemporaryConnectionResponse } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
2
+ import {
3
+ CloseTemporaryConnection,
4
+ TemporaryConnectionRequest,
5
+ TemporaryConnectionResponse
6
+ } from '../../proto/packages/trackerless-network/protos/NetworkRpc'
3
7
  import { ITemporaryConnectionRpc } from '../../proto/packages/trackerless-network/protos/NetworkRpc.server'
4
- import { DhtCallContext, ListeningRpcCommunicator } from '@streamr/dht'
8
+ import { ConnectionLocker, DhtAddress, DhtCallContext, ListeningRpcCommunicator, getNodeIdFromPeerDescriptor } from '@streamr/dht'
5
9
  import { DeliveryRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
6
10
  import { NodeList } from '../NodeList'
7
- import { toProtoRpcClient } from '@streamr/proto-rpc'
8
11
  import { DeliveryRpcRemote } from '../DeliveryRpcRemote'
9
12
  import { PeerDescriptor } from '../../proto/packages/dht/protos/DhtRpc'
10
- import { getNodeIdFromPeerDescriptor } from '../../identifiers'
13
+ import { Empty } from '../../proto/google/protobuf/empty'
11
14
  import { StreamPartID } from '@streamr/protocol'
12
15
 
13
16
  interface TemporaryConnectionRpcLocalConfig {
14
- streamPartId: StreamPartID
15
17
  rpcCommunicator: ListeningRpcCommunicator
16
18
  localPeerDescriptor: PeerDescriptor
19
+ streamPartId: StreamPartID
20
+ connectionLocker: ConnectionLocker
17
21
  }
18
22
 
23
+ const LOCK_ID_BASE = 'system/delivery/temporary-connection/'
24
+
19
25
  export class TemporaryConnectionRpcLocal implements ITemporaryConnectionRpc {
20
26
 
21
27
  private readonly config: TemporaryConnectionRpcLocalConfig
22
28
  private readonly temporaryNodes: NodeList
23
-
29
+ private readonly lockId: string
24
30
  constructor(config: TemporaryConnectionRpcLocalConfig) {
25
31
  this.config = config
32
+ // TODO use config option or named constant?
26
33
  this.temporaryNodes = new NodeList(getNodeIdFromPeerDescriptor(config.localPeerDescriptor), 10)
34
+ this.lockId = LOCK_ID_BASE + config.streamPartId
27
35
  }
28
36
 
29
37
  getNodes(): NodeList {
30
38
  return this.temporaryNodes
31
39
  }
32
40
 
33
- removeNode(peerDescriptor: PeerDescriptor): void {
34
- this.temporaryNodes.remove(peerDescriptor)
41
+ hasNode(node: DhtAddress): boolean {
42
+ return this.temporaryNodes.has(node)
43
+ }
44
+
45
+ removeNode(nodeId: DhtAddress): void {
46
+ this.temporaryNodes.remove(nodeId)
47
+ this.config.connectionLocker.weakUnlockConnection(nodeId, this.lockId)
35
48
  }
36
49
 
37
50
  async openConnection(
@@ -42,12 +55,19 @@ export class TemporaryConnectionRpcLocal implements ITemporaryConnectionRpc {
42
55
  const remote = new DeliveryRpcRemote(
43
56
  this.config.localPeerDescriptor,
44
57
  sender,
45
- this.config.streamPartId,
46
- toProtoRpcClient(new DeliveryRpcClient(this.config.rpcCommunicator.getRpcClientTransport()))
58
+ this.config.rpcCommunicator,
59
+ DeliveryRpcClient
47
60
  )
48
61
  this.temporaryNodes.add(remote)
62
+ this.config.connectionLocker.weakLockConnection(getNodeIdFromPeerDescriptor(sender), this.lockId)
49
63
  return {
50
64
  accepted: true
51
65
  }
52
66
  }
67
+
68
+ async closeConnection(_request: CloseTemporaryConnection, context: ServerCallContext): Promise<Empty> {
69
+ const senderId = getNodeIdFromPeerDescriptor((context as DhtCallContext).incomingSourceDescriptor!)
70
+ this.removeNode(senderId)
71
+ return {}
72
+ }
53
73
  }
@@ -1,11 +1,10 @@
1
- import { Remote } from '@streamr/dht'
1
+ import { RpcRemote, getNodeIdFromPeerDescriptor } from '@streamr/dht'
2
2
  import { Logger } from '@streamr/utils'
3
- import { getNodeIdFromPeerDescriptor } from '../../identifiers'
4
- import { ITemporaryConnectionRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
3
+ import { TemporaryConnectionRpcClient } from '../../proto/packages/trackerless-network/protos/NetworkRpc.client'
5
4
 
6
5
  const logger = new Logger(module)
7
6
 
8
- export class TemporaryConnectionRpcRemote extends Remote<ITemporaryConnectionRpcClient> {
7
+ export class TemporaryConnectionRpcRemote extends RpcRemote<TemporaryConnectionRpcClient> {
9
8
 
10
9
  async openConnection(): Promise<boolean> {
11
10
  try {
@@ -16,4 +15,15 @@ export class TemporaryConnectionRpcRemote extends Remote<ITemporaryConnectionRpc
16
15
  return false
17
16
  }
18
17
  }
18
+
19
+ async closeConnection(): Promise<void> {
20
+ try {
21
+ await this.getClient().closeConnection({}, this.formDhtRpcOptions({
22
+ connect: false,
23
+ notification: true
24
+ }))
25
+ } catch (err) {
26
+ logger.trace(`closeConnection to ${getNodeIdFromPeerDescriptor(this.getPeerDescriptor())} failed: ${err}`)
27
+ }
28
+ }
19
29
  }
@@ -1,4 +1,4 @@
1
- // @generated by protobuf-ts 2.9.1 with parameter server_generic,generate_dependencies,long_type_number
1
+ // @generated by protobuf-ts 2.9.3 with parameter server_generic,generate_dependencies,long_type_number
2
2
  // @generated from protobuf file "google/protobuf/any.proto" (package "google.protobuf", syntax proto3)
3
3
  // tslint:disable
4
4
  //
@@ -39,7 +39,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime";
39
39
  import { UnknownFieldHandler } from "@protobuf-ts/runtime";
40
40
  import type { PartialMessage } from "@protobuf-ts/runtime";
41
41
  import { reflectionMergePartial } from "@protobuf-ts/runtime";
42
- import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
43
42
  import { isJsonObject } from "@protobuf-ts/runtime";
44
43
  import { typeofJsonValue } from "@protobuf-ts/runtime";
45
44
  import type { JsonValue } from "@protobuf-ts/runtime";
@@ -272,8 +271,9 @@ class Any$Type extends MessageType<Any> {
272
271
  return name;
273
272
  }
274
273
  create(value?: PartialMessage<Any>): Any {
275
- const message = { typeUrl: "", value: new Uint8Array(0) };
276
- globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
274
+ const message = globalThis.Object.create((this.messagePrototype!));
275
+ message.typeUrl = "";
276
+ message.value = new Uint8Array(0);
277
277
  if (value !== undefined)
278
278
  reflectionMergePartial<Any>(this, message, value);
279
279
  return message;
@@ -1,4 +1,4 @@
1
- // @generated by protobuf-ts 2.9.1 with parameter server_generic,generate_dependencies,long_type_number
1
+ // @generated by protobuf-ts 2.9.3 with parameter server_generic,generate_dependencies,long_type_number
2
2
  // @generated from protobuf file "google/protobuf/empty.proto" (package "google.protobuf", syntax proto3)
3
3
  // tslint:disable
4
4
  //
@@ -39,7 +39,6 @@ import type { BinaryReadOptions } from "@protobuf-ts/runtime";
39
39
  import type { IBinaryReader } from "@protobuf-ts/runtime";
40
40
  import type { PartialMessage } from "@protobuf-ts/runtime";
41
41
  import { reflectionMergePartial } from "@protobuf-ts/runtime";
42
- import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
43
42
  import { MessageType } from "@protobuf-ts/runtime";
44
43
  /**
45
44
  * A generic empty message that you can re-use to avoid defining duplicated
@@ -62,8 +61,7 @@ class Empty$Type extends MessageType<Empty> {
62
61
  super("google.protobuf.Empty", []);
63
62
  }
64
63
  create(value?: PartialMessage<Empty>): Empty {
65
- const message = {};
66
- globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
64
+ const message = globalThis.Object.create((this.messagePrototype!));
67
65
  if (value !== undefined)
68
66
  reflectionMergePartial<Empty>(this, message, value);
69
67
  return message;
@@ -1,4 +1,4 @@
1
- // @generated by protobuf-ts 2.9.1 with parameter server_generic,generate_dependencies,long_type_number
1
+ // @generated by protobuf-ts 2.9.3 with parameter server_generic,generate_dependencies,long_type_number
2
2
  // @generated from protobuf file "google/protobuf/timestamp.proto" (package "google.protobuf", syntax proto3)
3
3
  // tslint:disable
4
4
  //
@@ -40,7 +40,6 @@ import type { IBinaryReader } from "@protobuf-ts/runtime";
40
40
  import { UnknownFieldHandler } from "@protobuf-ts/runtime";
41
41
  import type { PartialMessage } from "@protobuf-ts/runtime";
42
42
  import { reflectionMergePartial } from "@protobuf-ts/runtime";
43
- import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
44
43
  import { typeofJsonValue } from "@protobuf-ts/runtime";
45
44
  import type { JsonValue } from "@protobuf-ts/runtime";
46
45
  import type { JsonReadOptions } from "@protobuf-ts/runtime";
@@ -234,8 +233,9 @@ class Timestamp$Type extends MessageType<Timestamp> {
234
233
  return target;
235
234
  }
236
235
  create(value?: PartialMessage<Timestamp>): Timestamp {
237
- const message = { seconds: 0, nanos: 0 };
238
- globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
236
+ const message = globalThis.Object.create((this.messagePrototype!));
237
+ message.seconds = 0;
238
+ message.nanos = 0;
239
239
  if (value !== undefined)
240
240
  reflectionMergePartial<Timestamp>(this, message, value);
241
241
  return message;