@streamr/dht 100.0.0-testnet-two.1 → 100.0.0-testnet-two.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.
Files changed (184) hide show
  1. package/dist/package.json +5 -5
  2. package/dist/src/connection/ConnectionLockHandler.d.ts +11 -11
  3. package/dist/src/connection/ConnectionLockHandler.js.map +1 -1
  4. package/dist/src/connection/ConnectionLockRpcLocal.d.ts +3 -3
  5. package/dist/src/connection/ConnectionManager.d.ts +5 -4
  6. package/dist/src/connection/ConnectionManager.js +32 -36
  7. package/dist/src/connection/ConnectionManager.js.map +1 -1
  8. package/dist/src/connection/ManagedConnection.d.ts +2 -2
  9. package/dist/src/connection/simulator/Simulator.js.map +1 -1
  10. package/dist/src/connection/simulator/SimulatorConnection.js +21 -22
  11. package/dist/src/connection/simulator/SimulatorConnection.js.map +1 -1
  12. package/dist/src/connection/simulator/SimulatorConnector.js +4 -3
  13. package/dist/src/connection/simulator/SimulatorConnector.js.map +1 -1
  14. package/dist/src/connection/webrtc/NodeWebrtcConnection.js +11 -8
  15. package/dist/src/connection/webrtc/NodeWebrtcConnection.js.map +1 -1
  16. package/dist/src/connection/webrtc/WebrtcConnector.js +1 -1
  17. package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
  18. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +2 -2
  19. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +1 -1
  20. package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
  21. package/dist/src/connection/websocket/WebsocketConnector.js +6 -5
  22. package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
  23. package/dist/src/dht/DhtNode.d.ts +9 -8
  24. package/dist/src/dht/DhtNode.js +26 -22
  25. package/dist/src/dht/DhtNode.js.map +1 -1
  26. package/dist/src/dht/DhtNodeRpcLocal.d.ts +2 -1
  27. package/dist/src/dht/DhtNodeRpcLocal.js +2 -1
  28. package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
  29. package/dist/src/dht/DhtNodeRpcRemote.d.ts +6 -5
  30. package/dist/src/dht/DhtNodeRpcRemote.js +9 -7
  31. package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
  32. package/dist/src/dht/ExternalApiRpcLocal.d.ts +3 -3
  33. package/dist/src/dht/ExternalApiRpcLocal.js +3 -2
  34. package/dist/src/dht/ExternalApiRpcLocal.js.map +1 -1
  35. package/dist/src/dht/ExternalApiRpcRemote.d.ts +3 -2
  36. package/dist/src/dht/ExternalApiRpcRemote.js +3 -2
  37. package/dist/src/dht/ExternalApiRpcRemote.js.map +1 -1
  38. package/dist/src/dht/PeerManager.d.ts +9 -9
  39. package/dist/src/dht/PeerManager.js +35 -30
  40. package/dist/src/dht/PeerManager.js.map +1 -1
  41. package/dist/src/dht/contact/Contact.d.ts +2 -2
  42. package/dist/src/dht/contact/ContactList.d.ts +7 -7
  43. package/dist/src/dht/contact/ContactList.js.map +1 -1
  44. package/dist/src/dht/contact/RandomContactList.d.ts +4 -4
  45. package/dist/src/dht/contact/RandomContactList.js +2 -3
  46. package/dist/src/dht/contact/RandomContactList.js.map +1 -1
  47. package/dist/src/dht/contact/RpcRemote.d.ts +1 -4
  48. package/dist/src/dht/contact/RpcRemote.js +1 -5
  49. package/dist/src/dht/contact/RpcRemote.js.map +1 -1
  50. package/dist/src/dht/contact/SortedContactList.d.ts +13 -13
  51. package/dist/src/dht/contact/SortedContactList.js +5 -5
  52. package/dist/src/dht/contact/SortedContactList.js.map +1 -1
  53. package/dist/src/dht/discovery/DiscoverySession.d.ts +3 -2
  54. package/dist/src/dht/discovery/DiscoverySession.js +9 -9
  55. package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
  56. package/dist/src/dht/discovery/PeerDiscovery.d.ts +3 -1
  57. package/dist/src/dht/discovery/PeerDiscovery.js +18 -10
  58. package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
  59. package/dist/src/dht/recursive-operation/RecursiveOperationManager.d.ts +3 -3
  60. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +15 -14
  61. package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -1
  62. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js +2 -2
  63. package/dist/src/dht/recursive-operation/RecursiveOperationRpcRemote.js.map +1 -1
  64. package/dist/src/dht/recursive-operation/RecursiveOperationSession.d.ts +2 -1
  65. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js +6 -6
  66. package/dist/src/dht/recursive-operation/RecursiveOperationSession.js.map +1 -1
  67. package/dist/src/dht/routing/Router.d.ts +2 -2
  68. package/dist/src/dht/routing/Router.js +2 -2
  69. package/dist/src/dht/routing/Router.js.map +1 -1
  70. package/dist/src/dht/routing/RouterRpcLocal.js +3 -3
  71. package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
  72. package/dist/src/dht/routing/RouterRpcRemote.js +4 -2
  73. package/dist/src/dht/routing/RouterRpcRemote.js.map +1 -1
  74. package/dist/src/dht/routing/RoutingSession.d.ts +3 -3
  75. package/dist/src/dht/routing/RoutingSession.js +4 -4
  76. package/dist/src/dht/routing/RoutingSession.js.map +1 -1
  77. package/dist/src/dht/store/LocalDataStore.d.ts +6 -9
  78. package/dist/src/dht/store/LocalDataStore.js +27 -32
  79. package/dist/src/dht/store/LocalDataStore.js.map +1 -1
  80. package/dist/src/dht/store/StoreManager.d.ts +3 -3
  81. package/dist/src/dht/store/StoreManager.js +26 -23
  82. package/dist/src/dht/store/StoreManager.js.map +1 -1
  83. package/dist/src/dht/store/StoreRpcLocal.d.ts +2 -1
  84. package/dist/src/dht/store/StoreRpcLocal.js +10 -8
  85. package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
  86. package/dist/src/exports.d.ts +2 -0
  87. package/dist/src/exports.js +6 -1
  88. package/dist/src/exports.js.map +1 -1
  89. package/dist/src/helpers/AddressTools.js +2 -0
  90. package/dist/src/helpers/AddressTools.js.map +1 -1
  91. package/dist/src/helpers/PeerID.d.ts +2 -2
  92. package/dist/src/helpers/PeerID.js +3 -3
  93. package/dist/src/helpers/PeerID.js.map +1 -1
  94. package/dist/src/helpers/peerIdFromPeerDescriptor.d.ts +2 -2
  95. package/dist/src/helpers/peerIdFromPeerDescriptor.js +2 -3
  96. package/dist/src/helpers/peerIdFromPeerDescriptor.js.map +1 -1
  97. package/dist/src/identifiers.d.ts +6 -0
  98. package/dist/src/identifiers.js +23 -0
  99. package/dist/src/identifiers.js.map +1 -0
  100. package/package.json +5 -5
  101. package/src/connection/ConnectionLockHandler.ts +15 -15
  102. package/src/connection/ConnectionLockRpcLocal.ts +3 -3
  103. package/src/connection/ConnectionManager.ts +36 -46
  104. package/src/connection/ManagedConnection.ts +2 -2
  105. package/src/connection/simulator/Simulator.ts +2 -2
  106. package/src/connection/simulator/SimulatorConnection.ts +21 -23
  107. package/src/connection/simulator/SimulatorConnector.ts +6 -5
  108. package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -4
  109. package/src/connection/webrtc/NodeWebrtcConnection.ts +11 -10
  110. package/src/connection/webrtc/WebrtcConnector.ts +2 -3
  111. package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +2 -3
  112. package/src/connection/websocket/WebsocketConnector.ts +9 -9
  113. package/src/dht/DhtNode.ts +36 -35
  114. package/src/dht/DhtNodeRpcLocal.ts +3 -2
  115. package/src/dht/DhtNodeRpcRemote.ts +14 -12
  116. package/src/dht/ExternalApiRpcLocal.ts +15 -6
  117. package/src/dht/ExternalApiRpcRemote.ts +5 -4
  118. package/src/dht/PeerManager.ts +43 -38
  119. package/src/dht/contact/Contact.ts +2 -2
  120. package/src/dht/contact/ContactList.ts +7 -7
  121. package/src/dht/contact/RandomContactList.ts +6 -6
  122. package/src/dht/contact/RpcRemote.ts +0 -8
  123. package/src/dht/contact/SortedContactList.ts +22 -22
  124. package/src/dht/discovery/DiscoverySession.ts +16 -14
  125. package/src/dht/discovery/PeerDiscovery.ts +34 -12
  126. package/src/dht/recursive-operation/RecursiveOperationManager.ts +17 -17
  127. package/src/dht/recursive-operation/RecursiveOperationRpcRemote.ts +2 -2
  128. package/src/dht/recursive-operation/RecursiveOperationSession.ts +11 -11
  129. package/src/dht/routing/Router.ts +5 -5
  130. package/src/dht/routing/RouterRpcLocal.ts +3 -3
  131. package/src/dht/routing/RouterRpcRemote.ts +4 -4
  132. package/src/dht/routing/RoutingSession.ts +6 -8
  133. package/src/dht/store/LocalDataStore.ts +31 -40
  134. package/src/dht/store/StoreManager.ts +31 -31
  135. package/src/dht/store/StoreRpcLocal.ts +11 -9
  136. package/src/exports.ts +2 -0
  137. package/src/helpers/AddressTools.ts +2 -0
  138. package/src/helpers/PeerID.ts +4 -4
  139. package/src/helpers/peerIdFromPeerDescriptor.ts +4 -6
  140. package/src/identifiers.ts +20 -0
  141. package/test/RandomGraphSimulation.ts +3 -2
  142. package/test/benchmark/Find.test.ts +4 -3
  143. package/test/benchmark/KademliaCorrectness.test.ts +4 -4
  144. package/test/benchmark/SortedContactListBenchmark.test.ts +15 -14
  145. package/test/benchmark/kademlia-simulation/Contact.ts +7 -8
  146. package/test/benchmark/kademlia-simulation/KademliaSimulation.ts +2 -2
  147. package/test/benchmark/kademlia-simulation/SimulationNode.ts +10 -11
  148. package/test/data/generateGroundTruthData.ts +5 -4
  149. package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +2 -2
  150. package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +1 -1
  151. package/test/end-to-end/memory-leak.test.ts +3 -2
  152. package/test/integration/ConnectionManager.test.ts +3 -3
  153. package/test/integration/DhtJoinPeerDiscovery.test.ts +2 -1
  154. package/test/integration/DhtNodeExternalAPI.test.ts +7 -7
  155. package/test/integration/DhtNodeRpcRemote.test.ts +3 -2
  156. package/test/integration/Find.test.ts +3 -3
  157. package/test/integration/Layer1-scale.test.ts +3 -3
  158. package/test/integration/Mock-Layer1-Layer0.test.ts +6 -5
  159. package/test/integration/ReplicateData.test.ts +38 -30
  160. package/test/integration/RouteMessage.test.ts +9 -10
  161. package/test/integration/RouterRpcRemote.test.ts +1 -1
  162. package/test/integration/ScaleDownDht.test.ts +4 -4
  163. package/test/integration/SimultaneousConnections.test.ts +7 -14
  164. package/test/integration/Store.test.ts +17 -7
  165. package/test/integration/StoreAndDelete.test.ts +11 -10
  166. package/test/integration/StoreOnDhtWithTwoNodes.test.ts +7 -6
  167. package/test/integration/StoreRpcRemote.test.ts +3 -5
  168. package/test/unit/AddressTools.test.ts +4 -0
  169. package/test/unit/LocalDataStore.test.ts +41 -41
  170. package/test/unit/PeerManager.test.ts +7 -8
  171. package/test/unit/RandomContactList.test.ts +3 -3
  172. package/test/unit/RecursiveOperationManager.test.ts +2 -1
  173. package/test/unit/RecursiveOperationSession.test.ts +2 -3
  174. package/test/unit/Router.test.ts +2 -2
  175. package/test/unit/RoutingSession.test.ts +2 -2
  176. package/test/unit/SortedContactList.test.ts +6 -6
  177. package/test/unit/StoreManager.test.ts +26 -23
  178. package/test/utils/customMatchers.ts +3 -2
  179. package/test/utils/mock/mockDataEntry.ts +8 -6
  180. package/test/utils/utils.ts +4 -4
  181. package/dist/src/helpers/nodeId.d.ts +0 -6
  182. package/dist/src/helpers/nodeId.js +0 -31
  183. package/dist/src/helpers/nodeId.js.map +0 -1
  184. package/src/helpers/nodeId.ts +0 -28
@@ -12,7 +12,7 @@ import { Contact } from '../contact/Contact'
12
12
  import { RecursiveOperationRpcRemote } from '../recursive-operation/RecursiveOperationRpcRemote'
13
13
  import { EXISTING_CONNECTION_TIMEOUT } from '../contact/RpcRemote'
14
14
  import { getPreviousPeer } from './getPreviousPeer'
15
- import { NodeID, getNodeIdFromBinary } from '../../helpers/nodeId'
15
+ import { DhtAddress, getDhtAddressFromRaw } from '../../identifiers'
16
16
 
17
17
  const logger = new Logger(module)
18
18
 
@@ -28,7 +28,6 @@ class RemoteContact extends Contact {
28
28
  this.routerRpcRemote = new RouterRpcRemote(
29
29
  localPeerDescriptor,
30
30
  peer.getPeerDescriptor(),
31
- peer.getServiceId(),
32
31
  rpcCommunicator,
33
32
  RouterRpcClient,
34
33
  EXISTING_CONNECTION_TIMEOUT
@@ -36,7 +35,6 @@ class RemoteContact extends Contact {
36
35
  this.recursiveOperationRpcRemote = new RecursiveOperationRpcRemote(
37
36
  localPeerDescriptor,
38
37
  peer.getPeerDescriptor(),
39
- peer.getServiceId(),
40
38
  rpcCommunicator,
41
39
  RecursiveOperationRpcClient,
42
40
  EXISTING_CONNECTION_TIMEOUT
@@ -69,16 +67,16 @@ interface RoutingSessionConfig {
69
67
  rpcCommunicator: RoutingRpcCommunicator
70
68
  localPeerDescriptor: PeerDescriptor
71
69
  routedMessage: RouteMessageWrapper
72
- connections: Map<NodeID, DhtNodeRpcRemote>
70
+ connections: Map<DhtAddress, DhtNodeRpcRemote>
73
71
  parallelism: number
74
72
  mode: RoutingMode
75
- excludedNodeIds?: Set<NodeID>
73
+ excludedNodeIds?: Set<DhtAddress>
76
74
  }
77
75
 
78
76
  export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
79
77
 
80
78
  public readonly sessionId = v4()
81
- private ongoingRequests: Set<NodeID> = new Set()
79
+ private ongoingRequests: Set<DhtAddress> = new Set()
82
80
  private contactList: SortedContactList<RemoteContact>
83
81
  private failedHopCounter = 0
84
82
  private successfulHopCounter = 0
@@ -91,7 +89,7 @@ export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
91
89
  const previousPeer = getPreviousPeer(config.routedMessage)
92
90
  const previousId = previousPeer ? getNodeIdFromPeerDescriptor(previousPeer) : undefined
93
91
  this.contactList = new SortedContactList({
94
- referenceId: getNodeIdFromBinary(config.routedMessage.target),
92
+ referenceId: getDhtAddressFromRaw(config.routedMessage.target),
95
93
  maxSize: 10000, // TODO use config option or named constant?
96
94
  allowToContainReferenceId: true,
97
95
  nodeIdDistanceLimit: previousId,
@@ -100,7 +98,7 @@ export class RoutingSession extends EventEmitter<RoutingSessionEvents> {
100
98
  })
101
99
  }
102
100
 
103
- private onRequestFailed(nodeId: NodeID) {
101
+ private onRequestFailed(nodeId: DhtAddress) {
104
102
  logger.trace('onRequestFailed() sessionId: ' + this.sessionId)
105
103
  if (this.stopped) {
106
104
  return
@@ -1,9 +1,6 @@
1
- import { PeerID, PeerIDKey } from '../../helpers/PeerID'
2
1
  import { DataEntry } from '../../proto/packages/dht/protos/DhtRpc'
3
2
  import { MapWithTtl } from '../../helpers/MapWithTtl'
4
- import { NodeID, getNodeIdFromBinary } from '../../helpers/nodeId'
5
-
6
- type Key = Uint8Array
3
+ import { DhtAddress, getDhtAddressFromRaw } from '../../identifiers'
7
4
 
8
5
  export class LocalDataStore {
9
6
 
@@ -15,31 +12,30 @@ export class LocalDataStore {
15
12
 
16
13
  // A map into which each node can store one value per data key
17
14
  // The first key is the key of the data, the second key is the
18
- // NodeID of the creator of the data
19
- private store: Map<PeerIDKey, MapWithTtl<NodeID, DataEntry>> = new Map()
15
+ // DhtAddress of the creator of the data
16
+ private store: Map<DhtAddress, MapWithTtl<DhtAddress, DataEntry>> = new Map()
20
17
 
21
18
  public storeEntry(dataEntry: DataEntry): boolean {
22
- const dataKey = PeerID.fromValue(dataEntry.key).toKey()
23
- const creatorNodeId = getNodeIdFromBinary(dataEntry.creator)
24
- if (!this.store.has(dataKey)) {
25
- this.store.set(dataKey, new MapWithTtl((e) => Math.min(e.ttl, this.maxTtl)))
19
+ const key = getDhtAddressFromRaw(dataEntry.key)
20
+ const creatorNodeId = getDhtAddressFromRaw(dataEntry.creator)
21
+ if (!this.store.has(key)) {
22
+ this.store.set(key, new MapWithTtl((e) => Math.min(e.ttl, this.maxTtl)))
26
23
  }
27
- if (this.store.get(dataKey)!.has(creatorNodeId)) {
24
+ if (this.store.get(key)!.has(creatorNodeId)) {
28
25
  const storedMillis = (dataEntry.createdAt!.seconds * 1000) + (dataEntry.createdAt!.nanos / 1000000)
29
- const oldLocalEntry = this.store.get(dataKey)!.get(creatorNodeId)!
26
+ const oldLocalEntry = this.store.get(key)!.get(creatorNodeId)!
30
27
  const oldStoredMillis = (oldLocalEntry.createdAt!.seconds * 1000) + (oldLocalEntry.createdAt!.nanos / 1000000)
31
28
  // do nothing if old entry is newer than the one being replicated
32
29
  if (oldStoredMillis >= storedMillis) {
33
30
  return false
34
31
  }
35
32
  }
36
- this.store.get(dataKey)!.set(creatorNodeId, dataEntry)
33
+ this.store.get(key)!.set(creatorNodeId, dataEntry)
37
34
  return true
38
35
  }
39
36
 
40
- public markAsDeleted(key: Key, creator: NodeID): boolean {
41
- const dataKey = PeerID.fromValue(key).toKey()
42
- const item = this.store.get(dataKey)
37
+ public markAsDeleted(key: DhtAddress, creator: DhtAddress): boolean {
38
+ const item = this.store.get(key)
43
39
  if ((item === undefined) || !item.has(creator)) {
44
40
  return false
45
41
  }
@@ -48,43 +44,38 @@ export class LocalDataStore {
48
44
  return true
49
45
  }
50
46
 
51
- public* values(): IterableIterator<DataEntry> {
52
- for (const v of this.store.values()) {
53
- yield* v.values()
47
+ public* values(key?: DhtAddress): IterableIterator<DataEntry> {
48
+ if (key !== undefined) {
49
+ const map = this.store.get(key)
50
+ if (map !== undefined) {
51
+ yield* map.values()
52
+ }
53
+ } else {
54
+ for (const v of this.store.values()) {
55
+ yield* v.values()
56
+ }
54
57
  }
55
58
  }
56
59
 
57
- public getEntries(key: Key): Map<NodeID, DataEntry> {
58
- const dataEntries = new Map<NodeID, DataEntry>
59
- const mapKey = PeerID.fromValue(key).toKey()
60
- this.store.get(mapKey)?.forEach((value, key) => {
61
- dataEntries.set(key, value)
62
- })
63
- return dataEntries
64
- }
65
-
66
- public setStale(key: Key, creator: NodeID, stale: boolean): void {
67
- const mapKey = PeerID.fromValue(key).toKey()
68
- const storedEntry = this.store.get(mapKey)?.get(creator)
60
+ public setStale(key: DhtAddress, creator: DhtAddress, stale: boolean): void {
61
+ const storedEntry = this.store.get(key)?.get(creator)
69
62
  if (storedEntry) {
70
63
  storedEntry.stale = stale
71
64
  }
72
65
  }
73
66
 
74
- public setAllEntriesAsStale(key: Key): void {
75
- const mapKey = PeerID.fromValue(key).toKey()
76
- this.store.get(mapKey)?.forEach((value) => {
67
+ public setAllEntriesAsStale(key: DhtAddress): void {
68
+ this.store.get(key)?.forEach((value) => {
77
69
  value.stale = true
78
70
  })
79
71
  }
80
72
 
81
- public deleteEntry(key: Key, creator: NodeID): void {
82
- const mapKey = PeerID.fromValue(key).toKey()
83
- const storedEntry = this.store.get(mapKey)?.get(creator)
73
+ public deleteEntry(key: DhtAddress, creator: DhtAddress): void {
74
+ const storedEntry = this.store.get(key)?.get(creator)
84
75
  if (storedEntry) {
85
- this.store.get(mapKey)?.delete(creator)
86
- if (this.store.get(mapKey)?.size() === 0) {
87
- this.store.delete(mapKey)
76
+ this.store.get(key)?.delete(creator)
77
+ if (this.store.get(key)?.size() === 0) {
78
+ this.store.delete(key)
88
79
  }
89
80
  }
90
81
  }
@@ -7,7 +7,7 @@ import { ServerCallContext } from '@protobuf-ts/runtime-rpc'
7
7
  import { RoutingRpcCommunicator } from '../../transport/RoutingRpcCommunicator'
8
8
  import { RecursiveOperationManager } from '../recursive-operation/RecursiveOperationManager'
9
9
  import { areEqualPeerDescriptors, getNodeIdFromPeerDescriptor } from '../../helpers/peerIdFromPeerDescriptor'
10
- import { Logger, executeSafePromise, hexToBinary } from '@streamr/utils'
10
+ import { Logger, executeSafePromise } from '@streamr/utils'
11
11
  import { LocalDataStore } from './LocalDataStore'
12
12
  import { StoreRpcRemote } from './StoreRpcRemote'
13
13
  import { Timestamp } from '../../proto/google/protobuf/timestamp'
@@ -15,7 +15,7 @@ import { SortedContactList } from '../contact/SortedContactList'
15
15
  import { Contact } from '../contact/Contact'
16
16
  import { ServiceID } from '../../types/ServiceID'
17
17
  import { findIndex } from 'lodash'
18
- import { NodeID, areEqualNodeIds, getNodeIdFromBinary, getNodeIdFromDataKey } from '../../helpers/nodeId'
18
+ import { DhtAddress, getDhtAddressFromRaw, getRawFromDhtAddress } from '../../identifiers'
19
19
  import { StoreRpcLocal } from './StoreRpcLocal'
20
20
  import { getDistance } from '../PeerManager'
21
21
 
@@ -27,7 +27,7 @@ interface StoreManagerConfig {
27
27
  serviceId: ServiceID
28
28
  highestTtl: number
29
29
  redundancyFactor: number
30
- getClosestNeighborsTo: (id: Uint8Array, n?: number) => PeerDescriptor[]
30
+ getClosestNeighborsTo: (dataKey: DhtAddress, n?: number) => PeerDescriptor[]
31
31
  createRpcRemote: (contact: PeerDescriptor) => StoreRpcRemote
32
32
  }
33
33
 
@@ -46,7 +46,7 @@ export class StoreManager {
46
46
  const rpcLocal = new StoreRpcLocal({
47
47
  localDataStore: this.config.localDataStore,
48
48
  replicateDataToNeighbors: (incomingPeer: PeerDescriptor, dataEntry: DataEntry) => this.replicateDataToNeighbors(incomingPeer, dataEntry),
49
- selfIsWithinRedundancyFactor: (key: Uint8Array): boolean => this.selfIsWithinRedundancyFactor(key)
49
+ selfIsWithinRedundancyFactor: (key: DhtAddress): boolean => this.selfIsWithinRedundancyFactor(key)
50
50
  })
51
51
  this.config.rpcCommunicator.registerRpcMethod(StoreDataRequest, StoreDataResponse, 'storeData',
52
52
  (request: StoreDataRequest) => rpcLocal.storeData(request))
@@ -62,29 +62,27 @@ export class StoreManager {
62
62
 
63
63
  private replicateAndUpdateStaleState(dataEntry: DataEntry, newNode: PeerDescriptor): void {
64
64
  const newNodeId = getNodeIdFromPeerDescriptor(newNode)
65
+ const key = getDhtAddressFromRaw(dataEntry.key)
65
66
  // TODO use config option or named constant?
66
- const closestToData = this.config.getClosestNeighborsTo(dataEntry.key, 10)
67
+ const closestToData = this.config.getClosestNeighborsTo(key, 10)
67
68
  const sortedList = new SortedContactList<Contact>({
68
- referenceId: getNodeIdFromDataKey(dataEntry.key),
69
+ referenceId: key,
69
70
  maxSize: 20, // TODO use config option or named constant?
70
71
  allowToContainReferenceId: true,
71
72
  emitEvents: false
72
73
  })
73
74
  sortedList.addContact(new Contact(this.config.localPeerDescriptor))
74
75
  closestToData.forEach((neighbor) => {
75
- if (!areEqualNodeIds(newNodeId, getNodeIdFromPeerDescriptor(neighbor))) {
76
+ if (newNodeId !== getNodeIdFromPeerDescriptor(neighbor)) {
76
77
  sortedList.addContact(new Contact(neighbor))
77
78
  }
78
79
  })
79
- const selfIsPrimaryStorer = areEqualNodeIds(
80
- sortedList.getClosestContactId(),
81
- getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor)
82
- )
80
+ const selfIsPrimaryStorer = (sortedList.getClosestContactId() === getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor))
83
81
  if (selfIsPrimaryStorer) {
84
82
  sortedList.addContact(new Contact(newNode))
85
83
  const sorted = sortedList.getContactIds()
86
84
  // findIndex should never return -1 here because we just added the new node to the list
87
- const index = findIndex(sorted, (nodeId) => areEqualNodeIds(nodeId, newNodeId))
85
+ const index = findIndex(sorted, (nodeId) => (nodeId === newNodeId))
88
86
  // if new node is within the storageRedundancyFactor closest nodes to the data
89
87
  // do replicate data to it
90
88
  if (index < this.config.redundancyFactor) {
@@ -92,8 +90,8 @@ export class StoreManager {
92
90
  await this.replicateDataToContact(dataEntry, newNode)
93
91
  })
94
92
  }
95
- } else if (!this.selfIsWithinRedundancyFactor(dataEntry.key)) {
96
- this.config.localDataStore.setStale(dataEntry.key, getNodeIdFromBinary(dataEntry.creator), true)
93
+ } else if (!this.selfIsWithinRedundancyFactor(key)) {
94
+ this.config.localDataStore.setStale(key, getDhtAddressFromRaw(dataEntry.creator), true)
97
95
  }
98
96
  }
99
97
 
@@ -106,7 +104,7 @@ export class StoreManager {
106
104
  }
107
105
  }
108
106
 
109
- public async storeDataToDht(key: Uint8Array, data: Any, creator: NodeID): Promise<PeerDescriptor[]> {
107
+ public async storeDataToDht(key: DhtAddress, data: Any, creator: DhtAddress): Promise<PeerDescriptor[]> {
110
108
  logger.debug(`Storing data to DHT ${this.config.serviceId}`)
111
109
  const result = await this.config.recursiveOperationManager.execute(key, RecursiveOperation.FIND_NODE)
112
110
  const closestNodes = result.closestNodes
@@ -114,11 +112,13 @@ export class StoreManager {
114
112
  const ttl = this.config.highestTtl // ToDo: make TTL decrease according to some nice curve
115
113
  const createdAt = Timestamp.now()
116
114
  for (let i = 0; i < closestNodes.length && successfulNodes.length < this.config.redundancyFactor; i++) {
115
+ const keyRaw = getRawFromDhtAddress(key)
116
+ const creatorRaw = getRawFromDhtAddress(creator)
117
117
  if (areEqualPeerDescriptors(this.config.localPeerDescriptor, closestNodes[i])) {
118
118
  this.config.localDataStore.storeEntry({
119
- key,
119
+ key: keyRaw,
120
120
  data,
121
- creator: hexToBinary(creator),
121
+ creator: creatorRaw,
122
122
  createdAt,
123
123
  storedAt: Timestamp.now(),
124
124
  ttl,
@@ -131,9 +131,9 @@ export class StoreManager {
131
131
  const rpcRemote = this.config.createRpcRemote(closestNodes[i])
132
132
  try {
133
133
  await rpcRemote.storeData({
134
- key,
134
+ key: keyRaw,
135
135
  data,
136
- creator: hexToBinary(creator),
136
+ creator: creatorRaw,
137
137
  createdAt,
138
138
  ttl
139
139
  })
@@ -146,22 +146,21 @@ export class StoreManager {
146
146
  return successfulNodes
147
147
  }
148
148
 
149
- private selfIsWithinRedundancyFactor(dataKey: Uint8Array): boolean {
149
+ private selfIsWithinRedundancyFactor(dataKey: DhtAddress): boolean {
150
150
  const closestNeighbors = this.config.getClosestNeighborsTo(dataKey, this.config.redundancyFactor)
151
151
  if (closestNeighbors.length < this.config.redundancyFactor) {
152
152
  return true
153
153
  } else {
154
- const localNodeId = getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor)
155
- const furthestCloseNeighbor = getNodeIdFromPeerDescriptor(closestNeighbors[closestNeighbors.length - 1])
156
- const dataId = getNodeIdFromDataKey(dataKey)
157
- return getDistance(dataId, localNodeId) < getDistance(dataId, furthestCloseNeighbor)
154
+ const furthestCloseNeighbor = closestNeighbors[closestNeighbors.length - 1]
155
+ const dataKeyRaw = getRawFromDhtAddress(dataKey)
156
+ return getDistance(dataKeyRaw, this.config.localPeerDescriptor.nodeId) < getDistance(dataKeyRaw, furthestCloseNeighbor.nodeId)
158
157
  }
159
158
  }
160
159
 
161
160
  private async replicateDataToClosestNodes(): Promise<void> {
162
161
  const dataEntries = Array.from(this.config.localDataStore.values())
163
162
  await Promise.all(dataEntries.map(async (dataEntry) => {
164
- const neighbors = this.config.getClosestNeighborsTo(dataEntry.key, this.config.redundancyFactor)
163
+ const neighbors = this.config.getClosestNeighborsTo(getDhtAddressFromRaw(dataEntry.key), this.config.redundancyFactor)
165
164
  await Promise.all(neighbors.map(async (neighbor) => {
166
165
  const rpcRemote = this.config.createRpcRemote(neighbor)
167
166
  try {
@@ -177,10 +176,11 @@ export class StoreManager {
177
176
  // sort own contact list according to data id
178
177
  const localNodeId = getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor)
179
178
  const incomingNodeId = getNodeIdFromPeerDescriptor(incomingPeer)
179
+ const key = getDhtAddressFromRaw(dataEntry.key)
180
180
  // TODO use config option or named constant?
181
- const closestToData = this.config.getClosestNeighborsTo(dataEntry.key, 10)
181
+ const closestToData = this.config.getClosestNeighborsTo(key, 10)
182
182
  const sortedList = new SortedContactList<Contact>({
183
- referenceId: getNodeIdFromDataKey(dataEntry.key),
183
+ referenceId: key,
184
184
  maxSize: this.config.redundancyFactor,
185
185
  allowToContainReferenceId: true,
186
186
  emitEvents: false
@@ -189,20 +189,20 @@ export class StoreManager {
189
189
  closestToData.forEach((neighbor) => {
190
190
  sortedList.addContact(new Contact(neighbor))
191
191
  })
192
- const selfIsPrimaryStorer = areEqualNodeIds(sortedList.getClosestContactId(), localNodeId)
192
+ const selfIsPrimaryStorer = (sortedList.getClosestContactId() === localNodeId)
193
193
  const targets = selfIsPrimaryStorer
194
194
  // if we are the closest to the data, replicate to all storageRedundancyFactor nearest
195
195
  ? sortedList.getAllContacts()
196
196
  // if we are not the closest node to the data, replicate only to the closest one to the data
197
197
  : [sortedList.getAllContacts()[0]]
198
198
  targets.forEach((contact) => {
199
- const contactNodeId = getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())
200
- if (!areEqualNodeIds(incomingNodeId, contactNodeId) && !areEqualNodeIds(localNodeId, contactNodeId)) {
199
+ const contactNodeId = contact.getNodeId()
200
+ if ((incomingNodeId !== contactNodeId) && (localNodeId !== contactNodeId)) {
201
201
  setImmediate(() => {
202
202
  executeSafePromise(async () => {
203
203
  await this.replicateDataToContact(dataEntry, contact.getPeerDescriptor())
204
204
  logger.trace('replicateDataToContact() returned', {
205
- node: getNodeIdFromPeerDescriptor(contact.getPeerDescriptor()),
205
+ node: contactNodeId,
206
206
  replicateOnlyToClosest: !selfIsPrimaryStorer
207
207
  })
208
208
  })
@@ -11,11 +11,12 @@ import {
11
11
  import { IStoreRpc } from '../../proto/packages/dht/protos/DhtRpc.server'
12
12
  import { DhtCallContext } from '../../rpc-protocol/DhtCallContext'
13
13
  import { LocalDataStore } from './LocalDataStore'
14
+ import { DhtAddress, getDhtAddressFromRaw } from '../../identifiers'
14
15
 
15
16
  interface StoreRpcLocalConfig {
16
17
  localDataStore: LocalDataStore
17
18
  replicateDataToNeighbors: (incomingPeer: PeerDescriptor, dataEntry: DataEntry) => void
18
- selfIsWithinRedundancyFactor: (key: Uint8Array) => boolean
19
+ selfIsWithinRedundancyFactor: (key: DhtAddress) => boolean
19
20
  }
20
21
 
21
22
  const logger = new Logger(module)
@@ -30,15 +31,15 @@ export class StoreRpcLocal implements IStoreRpc {
30
31
 
31
32
  async storeData(request: StoreDataRequest): Promise<StoreDataResponse> {
32
33
  logger.trace('storeData()')
33
- const { key, data, creator, createdAt, ttl } = request
34
+ const key = getDhtAddressFromRaw(request.key)
34
35
  const selfIsOneOfClosestPeers = this.config.selfIsWithinRedundancyFactor(key)
35
36
  this.config.localDataStore.storeEntry({
36
- key,
37
- data,
38
- creator,
39
- createdAt,
37
+ key: request.key,
38
+ data: request.data,
39
+ creator: request.creator,
40
+ createdAt: request.createdAt,
40
41
  storedAt: Timestamp.now(),
41
- ttl,
42
+ ttl: request.ttl,
42
43
  stale: !selfIsOneOfClosestPeers,
43
44
  deleted: false
44
45
  })
@@ -55,8 +56,9 @@ export class StoreRpcLocal implements IStoreRpc {
55
56
  if (wasStored) {
56
57
  this.config.replicateDataToNeighbors((context as DhtCallContext).incomingSourceDescriptor!, request.entry!)
57
58
  }
58
- if (!this.config.selfIsWithinRedundancyFactor(dataEntry.key)) {
59
- this.config.localDataStore.setAllEntriesAsStale(dataEntry.key)
59
+ const key = getDhtAddressFromRaw(dataEntry.key)
60
+ if (!this.config.selfIsWithinRedundancyFactor(key)) {
61
+ this.config.localDataStore.setAllEntriesAsStale(key)
60
62
  }
61
63
  logger.trace('server-side replicateData() at end')
62
64
  return {}
package/src/exports.ts CHANGED
@@ -19,3 +19,5 @@ export { ManagedConnection } from './connection/ManagedConnection'
19
19
  export { ConnectionType } from './connection/IConnection'
20
20
  export { PeerID } from './helpers/PeerID'
21
21
  export { ServiceID } from './types/ServiceID'
22
+ export { DhtAddress, DhtAddressRaw, getDhtAddressFromRaw, getRawFromDhtAddress } from './identifiers'
23
+ export { getNodeIdFromPeerDescriptor } from './helpers/peerIdFromPeerDescriptor'
@@ -1,10 +1,12 @@
1
1
  import ipaddr from 'ipaddr.js'
2
2
 
3
3
  // IPv4 private address ranges as specified by RFC 1918
4
+ // and private loopback addresses
4
5
  const IPv4PrivateRanges = [
5
6
  '10.0.0.0/8',
6
7
  '172.16.0.0/12',
7
8
  '192.168.0.0/16',
9
+ '127.0.0.0/8'
8
10
  ].map((a) => ipaddr.parseCIDR(a))
9
11
 
10
12
  export function isPrivateIPv4(address: string): boolean {
@@ -2,7 +2,7 @@ import { BrandedString, binaryToHex } from '@streamr/utils'
2
2
  import { UUID } from './UUID'
3
3
  import { IllegalArguments } from './errors'
4
4
  import crypto from 'crypto'
5
- import { NodeID, getNodeIdFromBinary } from './nodeId'
5
+ import { DhtAddress, getDhtAddressFromRaw } from '../identifiers'
6
6
 
7
7
  export type PeerIDKey = BrandedString<'PeerIDKey'>
8
8
 
@@ -69,15 +69,15 @@ export class PeerID {
69
69
  }
70
70
 
71
71
  toString(): string {
72
- return PeerID.textDecoder.decode(this.data) //utf8ArrayToString(this.data)
72
+ return PeerID.textDecoder.decode(this.data)
73
73
  }
74
74
 
75
75
  toKey(): PeerIDKey {
76
76
  return this.key
77
77
  }
78
78
 
79
- toNodeId(): NodeID {
80
- return getNodeIdFromBinary(this.data)
79
+ toNodeId(): DhtAddress {
80
+ return getDhtAddressFromRaw(this.data)
81
81
  }
82
82
 
83
83
  get value(): Uint8Array {
@@ -1,16 +1,14 @@
1
- import { areEqualBinaries, binaryToHex } from '@streamr/utils'
1
+ import { areEqualBinaries } from '@streamr/utils'
2
2
  import { PeerDescriptor } from '../proto/packages/dht/protos/DhtRpc'
3
3
  import { PeerID, PeerIDKey, createPeerIDKey } from './PeerID'
4
- import { NodeID } from './nodeId'
4
+ import { DhtAddress, getDhtAddressFromRaw } from '../identifiers'
5
5
 
6
6
  export const peerIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): PeerID => {
7
7
  return PeerID.fromValue(peerDescriptor.nodeId)
8
8
  }
9
9
 
10
- // TODO could use this in trackerless-network (instead of copy-pasted same implementation)
11
- // and move this to nodeId.ts
12
- export const getNodeIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): NodeID => {
13
- return binaryToHex(peerDescriptor.nodeId) as unknown as NodeID
10
+ export const getNodeIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): DhtAddress => {
11
+ return getDhtAddressFromRaw(peerDescriptor.nodeId)
14
12
  }
15
13
 
16
14
  export const keyFromPeerDescriptor = (peerDescriptor: PeerDescriptor): PeerIDKey => {
@@ -0,0 +1,20 @@
1
+ import { BrandedString, binaryToHex, hexToBinary } from '@streamr/utils'
2
+ import crypto from 'crypto'
3
+
4
+ // https://www.scs.stanford.edu/~dm/home/papers/kpos.pdf
5
+ const KADEMLIA_ID_LENGTH_IN_BYTES = 20
6
+
7
+ export type DhtAddress = BrandedString<'DhtAddress'>
8
+ export type DhtAddressRaw = Uint8Array
9
+
10
+ export const getDhtAddressFromRaw = (raw: DhtAddressRaw): DhtAddress => {
11
+ return binaryToHex(raw) as unknown as DhtAddress
12
+ }
13
+
14
+ export const getRawFromDhtAddress = (address: DhtAddress): DhtAddressRaw => {
15
+ return hexToBinary(address) as unknown as DhtAddressRaw
16
+ }
17
+
18
+ export const createRandomDhtAddress = (): DhtAddress => {
19
+ return getDhtAddressFromRaw(crypto.randomBytes(KADEMLIA_ID_LENGTH_IN_BYTES))
20
+ }
@@ -2,13 +2,14 @@
2
2
 
3
3
  import KBucket from 'k-bucket'
4
4
  import { range } from 'lodash'
5
+ import { DhtAddressRaw } from '../src/identifiers'
5
6
 
6
- const compareIds = (id1: Uint8Array, id2: Uint8Array) => {
7
+ const compareIds = (id1: DhtAddressRaw, id2: DhtAddressRaw) => {
7
8
  const sorted = [id1, id2].sort()
8
9
  return KBucket.distance(sorted[0], sorted[1])
9
10
  }
10
11
 
11
- const generateIDs = (count: number): Uint8Array[] => {
12
+ const generateIDs = (count: number): DhtAddressRaw[] => {
12
13
  return range(count).map((i) => new Uint8Array([i, 1, 1]))
13
14
  }
14
15
 
@@ -9,6 +9,7 @@ import { PeerID } from '../../src/helpers/PeerID'
9
9
  import { getNodeIdFromPeerDescriptor, peerIdFromPeerDescriptor } from '../../src/helpers/peerIdFromPeerDescriptor'
10
10
  import { Logger, wait } from '@streamr/utils'
11
11
  import { debugVars } from '../../src/helpers/debugHelpers'
12
+ import { getDhtAddressFromRaw } from '../../src/identifiers'
12
13
 
13
14
  const logger = new Logger(module)
14
15
 
@@ -28,10 +29,10 @@ describe('Find correctness', () => {
28
29
  beforeEach(async () => {
29
30
 
30
31
  nodes = []
31
- entryPoint = await createMockConnectionDhtNode(simulator, Uint8Array.from(dhtIds[0].data), undefined)
32
+ entryPoint = await createMockConnectionDhtNode(simulator, getDhtAddressFromRaw(Uint8Array.from(dhtIds[0].data)), undefined)
32
33
 
33
34
  for (let i = 1; i < NUM_NODES; i++) {
34
- const node = await createMockConnectionDhtNode(simulator, Uint8Array.from(dhtIds[i].data), undefined)
35
+ const node = await createMockConnectionDhtNode(simulator, getDhtAddressFromRaw(Uint8Array.from(dhtIds[i].data)), undefined)
35
36
  nodes.push(node)
36
37
  }
37
38
  })
@@ -65,7 +66,7 @@ describe('Find correctness', () => {
65
66
 
66
67
  logger.info('starting find')
67
68
  const targetId = Uint8Array.from(dhtIds[9].data)
68
- const results = await nodes[159].executeRecursiveOperation(targetId, RecursiveOperation.FIND_NODE)
69
+ const results = await nodes[159].executeRecursiveOperation(getDhtAddressFromRaw(targetId), RecursiveOperation.FIND_NODE)
69
70
  logger.info('find over')
70
71
  expect(results.closestNodes).toBeGreaterThanOrEqual(5)
71
72
  expect(PeerID.fromValue(targetId).equals(peerIdFromPeerDescriptor(results.closestNodes[0])))
@@ -5,7 +5,7 @@ import { getNodeIdFromPeerDescriptor } from '../../src/helpers/peerIdFromPeerDes
5
5
  import { createMockConnectionDhtNode } from '../utils/utils'
6
6
  import { execSync } from 'child_process'
7
7
  import fs from 'fs'
8
- import { NodeID } from '../../src/helpers/nodeId'
8
+ import { DhtAddress, getDhtAddressFromRaw } from '../../src/identifiers'
9
9
 
10
10
  describe('Kademlia correctness', () => {
11
11
  let entryPoint: DhtNode
@@ -13,7 +13,7 @@ describe('Kademlia correctness', () => {
13
13
  const simulator = new Simulator()
14
14
  const NUM_NODES = 1000
15
15
 
16
- const nodeIndicesById: Record<NodeID, number> = {}
16
+ const nodeIndicesById: Record<DhtAddress, number> = {}
17
17
 
18
18
  if (!fs.existsSync('test/data/nodeids.json')) {
19
19
  console.log('gound truth data does not exist yet, generating..')
@@ -27,12 +27,12 @@ describe('Kademlia correctness', () => {
27
27
  beforeEach(async () => {
28
28
 
29
29
  nodes = []
30
- entryPoint = await createMockConnectionDhtNode(simulator, Uint8Array.from(dhtIds[0].data), 8)
30
+ entryPoint = await createMockConnectionDhtNode(simulator, getDhtAddressFromRaw(Uint8Array.from(dhtIds[0].data)), 8)
31
31
  nodes.push(entryPoint)
32
32
  nodeIndicesById[entryPoint.getNodeId()] = 0
33
33
 
34
34
  for (let i = 1; i < NUM_NODES; i++) {
35
- const node = await createMockConnectionDhtNode(simulator, Uint8Array.from(dhtIds[i].data))
35
+ const node = await createMockConnectionDhtNode(simulator, getDhtAddressFromRaw(Uint8Array.from(dhtIds[i].data)))
36
36
  nodeIndicesById[node.getNodeId()] = i
37
37
  nodes.push(node)
38
38
  }