@streamr/dht 100.0.0-testnet-two.1 → 100.0.0-testnet-two.2
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 -5
- package/dist/src/connection/ConnectionLockHandler.d.ts +11 -11
- package/dist/src/connection/ConnectionLockHandler.js.map +1 -1
- package/dist/src/connection/ConnectionLockRpcLocal.d.ts +3 -3
- package/dist/src/connection/ConnectionManager.js +3 -3
- package/dist/src/connection/ConnectionManager.js.map +1 -1
- package/dist/src/connection/ManagedConnection.d.ts +2 -2
- package/dist/src/connection/simulator/Simulator.js.map +1 -1
- package/dist/src/connection/simulator/SimulatorConnector.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnector.js.map +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.d.ts +2 -2
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js +1 -1
- package/dist/src/connection/webrtc/WebrtcConnectorRpcLocal.js.map +1 -1
- package/dist/src/connection/websocket/WebsocketConnector.js +2 -2
- package/dist/src/connection/websocket/WebsocketConnector.js.map +1 -1
- package/dist/src/dht/DhtNode.d.ts +9 -8
- package/dist/src/dht/DhtNode.js +21 -16
- package/dist/src/dht/DhtNode.js.map +1 -1
- package/dist/src/dht/DhtNodeRpcLocal.d.ts +2 -1
- package/dist/src/dht/DhtNodeRpcLocal.js +2 -1
- package/dist/src/dht/DhtNodeRpcLocal.js.map +1 -1
- package/dist/src/dht/DhtNodeRpcRemote.d.ts +6 -5
- package/dist/src/dht/DhtNodeRpcRemote.js +9 -7
- package/dist/src/dht/DhtNodeRpcRemote.js.map +1 -1
- package/dist/src/dht/ExternalApiRpcLocal.d.ts +3 -3
- package/dist/src/dht/ExternalApiRpcLocal.js +3 -2
- package/dist/src/dht/ExternalApiRpcLocal.js.map +1 -1
- package/dist/src/dht/ExternalApiRpcRemote.d.ts +3 -2
- package/dist/src/dht/ExternalApiRpcRemote.js +3 -2
- package/dist/src/dht/ExternalApiRpcRemote.js.map +1 -1
- package/dist/src/dht/PeerManager.d.ts +9 -9
- package/dist/src/dht/PeerManager.js +12 -12
- package/dist/src/dht/PeerManager.js.map +1 -1
- package/dist/src/dht/contact/Contact.d.ts +2 -2
- package/dist/src/dht/contact/ContactList.d.ts +7 -7
- package/dist/src/dht/contact/ContactList.js.map +1 -1
- package/dist/src/dht/contact/RandomContactList.d.ts +4 -4
- package/dist/src/dht/contact/RandomContactList.js +2 -3
- package/dist/src/dht/contact/RandomContactList.js.map +1 -1
- package/dist/src/dht/contact/RpcRemote.d.ts +1 -4
- package/dist/src/dht/contact/RpcRemote.js +1 -5
- package/dist/src/dht/contact/RpcRemote.js.map +1 -1
- package/dist/src/dht/contact/SortedContactList.d.ts +13 -13
- package/dist/src/dht/contact/SortedContactList.js +5 -5
- package/dist/src/dht/contact/SortedContactList.js.map +1 -1
- package/dist/src/dht/discovery/DiscoverySession.d.ts +3 -2
- package/dist/src/dht/discovery/DiscoverySession.js +9 -9
- package/dist/src/dht/discovery/DiscoverySession.js.map +1 -1
- package/dist/src/dht/discovery/PeerDiscovery.d.ts +3 -1
- package/dist/src/dht/discovery/PeerDiscovery.js +16 -9
- package/dist/src/dht/discovery/PeerDiscovery.js.map +1 -1
- package/dist/src/dht/recursive-operation/RecursiveOperationManager.d.ts +3 -3
- package/dist/src/dht/recursive-operation/RecursiveOperationManager.js +12 -11
- package/dist/src/dht/recursive-operation/RecursiveOperationManager.js.map +1 -1
- package/dist/src/dht/recursive-operation/RecursiveOperationSession.d.ts +2 -1
- package/dist/src/dht/recursive-operation/RecursiveOperationSession.js +6 -6
- package/dist/src/dht/recursive-operation/RecursiveOperationSession.js.map +1 -1
- package/dist/src/dht/routing/Router.d.ts +2 -2
- package/dist/src/dht/routing/Router.js +2 -2
- package/dist/src/dht/routing/Router.js.map +1 -1
- package/dist/src/dht/routing/RouterRpcLocal.js +3 -3
- package/dist/src/dht/routing/RouterRpcLocal.js.map +1 -1
- package/dist/src/dht/routing/RoutingSession.d.ts +3 -3
- package/dist/src/dht/routing/RoutingSession.js +4 -4
- package/dist/src/dht/routing/RoutingSession.js.map +1 -1
- package/dist/src/dht/store/LocalDataStore.d.ts +6 -8
- package/dist/src/dht/store/LocalDataStore.js +18 -24
- package/dist/src/dht/store/LocalDataStore.js.map +1 -1
- package/dist/src/dht/store/StoreManager.d.ts +3 -3
- package/dist/src/dht/store/StoreManager.js +20 -21
- package/dist/src/dht/store/StoreManager.js.map +1 -1
- package/dist/src/dht/store/StoreRpcLocal.d.ts +2 -1
- package/dist/src/dht/store/StoreRpcLocal.js +10 -8
- package/dist/src/dht/store/StoreRpcLocal.js.map +1 -1
- package/dist/src/exports.d.ts +2 -0
- package/dist/src/exports.js +6 -1
- package/dist/src/exports.js.map +1 -1
- package/dist/src/helpers/AddressTools.js +2 -0
- package/dist/src/helpers/AddressTools.js.map +1 -1
- package/dist/src/helpers/PeerID.d.ts +2 -2
- package/dist/src/helpers/PeerID.js +3 -3
- package/dist/src/helpers/PeerID.js.map +1 -1
- package/dist/src/helpers/peerIdFromPeerDescriptor.d.ts +2 -2
- package/dist/src/helpers/peerIdFromPeerDescriptor.js +2 -1
- package/dist/src/helpers/peerIdFromPeerDescriptor.js.map +1 -1
- package/dist/src/identifiers.d.ts +6 -0
- package/dist/src/identifiers.js +23 -0
- package/dist/src/identifiers.js.map +1 -0
- package/package.json +5 -5
- package/src/connection/ConnectionLockHandler.ts +15 -15
- package/src/connection/ConnectionLockRpcLocal.ts +3 -3
- package/src/connection/ConnectionManager.ts +4 -7
- package/src/connection/ManagedConnection.ts +2 -2
- package/src/connection/simulator/Simulator.ts +2 -2
- package/src/connection/simulator/SimulatorConnector.ts +2 -2
- package/src/connection/webrtc/BrowserWebrtcConnection.ts +0 -4
- package/src/connection/webrtc/WebrtcConnector.ts +2 -3
- package/src/connection/webrtc/WebrtcConnectorRpcLocal.ts +2 -3
- package/src/connection/websocket/WebsocketConnector.ts +5 -6
- package/src/dht/DhtNode.ts +31 -29
- package/src/dht/DhtNodeRpcLocal.ts +3 -2
- package/src/dht/DhtNodeRpcRemote.ts +14 -12
- package/src/dht/ExternalApiRpcLocal.ts +15 -6
- package/src/dht/ExternalApiRpcRemote.ts +5 -4
- package/src/dht/PeerManager.ts +20 -20
- package/src/dht/contact/Contact.ts +2 -2
- package/src/dht/contact/ContactList.ts +7 -7
- package/src/dht/contact/RandomContactList.ts +6 -6
- package/src/dht/contact/RpcRemote.ts +0 -8
- package/src/dht/contact/SortedContactList.ts +22 -22
- package/src/dht/discovery/DiscoverySession.ts +16 -14
- package/src/dht/discovery/PeerDiscovery.ts +32 -11
- package/src/dht/recursive-operation/RecursiveOperationManager.ts +14 -14
- package/src/dht/recursive-operation/RecursiveOperationSession.ts +11 -11
- package/src/dht/routing/Router.ts +5 -5
- package/src/dht/routing/RouterRpcLocal.ts +3 -3
- package/src/dht/routing/RoutingSession.ts +6 -8
- package/src/dht/store/LocalDataStore.ts +25 -33
- package/src/dht/store/StoreManager.ts +25 -29
- package/src/dht/store/StoreRpcLocal.ts +11 -9
- package/src/exports.ts +2 -0
- package/src/helpers/AddressTools.ts +2 -0
- package/src/helpers/PeerID.ts +4 -4
- package/src/helpers/peerIdFromPeerDescriptor.ts +4 -4
- package/src/identifiers.ts +20 -0
- package/test/RandomGraphSimulation.ts +3 -2
- package/test/benchmark/Find.test.ts +4 -3
- package/test/benchmark/KademliaCorrectness.test.ts +4 -4
- package/test/benchmark/SortedContactListBenchmark.test.ts +15 -14
- package/test/benchmark/kademlia-simulation/Contact.ts +7 -8
- package/test/benchmark/kademlia-simulation/KademliaSimulation.ts +2 -2
- package/test/benchmark/kademlia-simulation/SimulationNode.ts +10 -11
- package/test/data/generateGroundTruthData.ts +5 -4
- package/test/end-to-end/Layer0Webrtc-Layer1.test.ts +2 -2
- package/test/end-to-end/RecoveryFromFailedAutoCertification.test.ts +1 -1
- package/test/end-to-end/memory-leak.test.ts +3 -2
- package/test/integration/ConnectionManager.test.ts +3 -3
- package/test/integration/DhtJoinPeerDiscovery.test.ts +2 -1
- package/test/integration/DhtNodeExternalAPI.test.ts +7 -7
- package/test/integration/DhtNodeRpcRemote.test.ts +3 -2
- package/test/integration/Find.test.ts +3 -3
- package/test/integration/Layer1-scale.test.ts +3 -3
- package/test/integration/Mock-Layer1-Layer0.test.ts +6 -5
- package/test/integration/ReplicateData.test.ts +25 -23
- package/test/integration/RouteMessage.test.ts +9 -10
- package/test/integration/RouterRpcRemote.test.ts +1 -1
- package/test/integration/ScaleDownDht.test.ts +4 -4
- package/test/integration/SimultaneousConnections.test.ts +7 -14
- package/test/integration/Store.test.ts +17 -7
- package/test/integration/StoreAndDelete.test.ts +11 -10
- package/test/integration/StoreOnDhtWithTwoNodes.test.ts +7 -6
- package/test/integration/StoreRpcRemote.test.ts +3 -5
- package/test/unit/AddressTools.test.ts +4 -0
- package/test/unit/LocalDataStore.test.ts +37 -29
- package/test/unit/PeerManager.test.ts +7 -8
- package/test/unit/RandomContactList.test.ts +3 -3
- package/test/unit/RecursiveOperationManager.test.ts +2 -1
- package/test/unit/RecursiveOperationSession.test.ts +2 -3
- package/test/unit/Router.test.ts +2 -2
- package/test/unit/RoutingSession.test.ts +2 -2
- package/test/unit/SortedContactList.test.ts +6 -6
- package/test/unit/StoreManager.test.ts +26 -23
- package/test/utils/customMatchers.ts +3 -2
- package/test/utils/mock/mockDataEntry.ts +8 -6
- package/test/utils/utils.ts +4 -4
- package/dist/src/helpers/nodeId.d.ts +0 -6
- package/dist/src/helpers/nodeId.js +0 -31
- package/dist/src/helpers/nodeId.js.map +0 -1
- package/src/helpers/nodeId.ts +0 -28
|
@@ -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 {
|
|
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
|
-
//
|
|
19
|
-
private store: 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
|
|
23
|
-
const creatorNodeId =
|
|
24
|
-
if (!this.store.has(
|
|
25
|
-
this.store.set(
|
|
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(
|
|
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(
|
|
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(
|
|
33
|
+
this.store.get(key)!.set(creatorNodeId, dataEntry)
|
|
37
34
|
return true
|
|
38
35
|
}
|
|
39
36
|
|
|
40
|
-
public markAsDeleted(key:
|
|
41
|
-
const
|
|
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
|
}
|
|
@@ -54,37 +50,33 @@ export class LocalDataStore {
|
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
52
|
|
|
57
|
-
public getEntries(key:
|
|
58
|
-
const dataEntries = new Map<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
dataEntries.set(key, value)
|
|
53
|
+
public getEntries(key: DhtAddress): Map<DhtAddress, DataEntry> {
|
|
54
|
+
const dataEntries = new Map<DhtAddress, DataEntry>
|
|
55
|
+
this.store.get(key)?.forEach((value, creator) => {
|
|
56
|
+
dataEntries.set(creator, value)
|
|
62
57
|
})
|
|
63
58
|
return dataEntries
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
public setStale(key:
|
|
67
|
-
const
|
|
68
|
-
const storedEntry = this.store.get(mapKey)?.get(creator)
|
|
61
|
+
public setStale(key: DhtAddress, creator: DhtAddress, stale: boolean): void {
|
|
62
|
+
const storedEntry = this.store.get(key)?.get(creator)
|
|
69
63
|
if (storedEntry) {
|
|
70
64
|
storedEntry.stale = stale
|
|
71
65
|
}
|
|
72
66
|
}
|
|
73
67
|
|
|
74
|
-
public setAllEntriesAsStale(key:
|
|
75
|
-
|
|
76
|
-
this.store.get(mapKey)?.forEach((value) => {
|
|
68
|
+
public setAllEntriesAsStale(key: DhtAddress): void {
|
|
69
|
+
this.store.get(key)?.forEach((value) => {
|
|
77
70
|
value.stale = true
|
|
78
71
|
})
|
|
79
72
|
}
|
|
80
73
|
|
|
81
|
-
public deleteEntry(key:
|
|
82
|
-
const
|
|
83
|
-
const storedEntry = this.store.get(mapKey)?.get(creator)
|
|
74
|
+
public deleteEntry(key: DhtAddress, creator: DhtAddress): void {
|
|
75
|
+
const storedEntry = this.store.get(key)?.get(creator)
|
|
84
76
|
if (storedEntry) {
|
|
85
|
-
this.store.get(
|
|
86
|
-
if (this.store.get(
|
|
87
|
-
this.store.delete(
|
|
77
|
+
this.store.get(key)?.delete(creator)
|
|
78
|
+
if (this.store.get(key)?.size() === 0) {
|
|
79
|
+
this.store.delete(key)
|
|
88
80
|
}
|
|
89
81
|
}
|
|
90
82
|
}
|
|
@@ -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
|
|
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 {
|
|
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: (
|
|
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:
|
|
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))
|
|
@@ -63,28 +63,25 @@ export class StoreManager {
|
|
|
63
63
|
private replicateAndUpdateStaleState(dataEntry: DataEntry, newNode: PeerDescriptor): void {
|
|
64
64
|
const newNodeId = getNodeIdFromPeerDescriptor(newNode)
|
|
65
65
|
// TODO use config option or named constant?
|
|
66
|
-
const closestToData = this.config.getClosestNeighborsTo(dataEntry.key, 10)
|
|
66
|
+
const closestToData = this.config.getClosestNeighborsTo(getDhtAddressFromRaw(dataEntry.key), 10)
|
|
67
67
|
const sortedList = new SortedContactList<Contact>({
|
|
68
|
-
referenceId:
|
|
68
|
+
referenceId: getDhtAddressFromRaw(dataEntry.key),
|
|
69
69
|
maxSize: 20, // TODO use config option or named constant?
|
|
70
70
|
allowToContainReferenceId: true,
|
|
71
71
|
emitEvents: false
|
|
72
72
|
})
|
|
73
73
|
sortedList.addContact(new Contact(this.config.localPeerDescriptor))
|
|
74
74
|
closestToData.forEach((neighbor) => {
|
|
75
|
-
if (
|
|
75
|
+
if (newNodeId !== getNodeIdFromPeerDescriptor(neighbor)) {
|
|
76
76
|
sortedList.addContact(new Contact(neighbor))
|
|
77
77
|
}
|
|
78
78
|
})
|
|
79
|
-
const selfIsPrimaryStorer =
|
|
80
|
-
sortedList.getClosestContactId(),
|
|
81
|
-
getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor)
|
|
82
|
-
)
|
|
79
|
+
const selfIsPrimaryStorer = (sortedList.getClosestContactId() === getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor))
|
|
83
80
|
if (selfIsPrimaryStorer) {
|
|
84
81
|
sortedList.addContact(new Contact(newNode))
|
|
85
82
|
const sorted = sortedList.getContactIds()
|
|
86
83
|
// findIndex should never return -1 here because we just added the new node to the list
|
|
87
|
-
const index = findIndex(sorted, (nodeId) =>
|
|
84
|
+
const index = findIndex(sorted, (nodeId) => (nodeId === newNodeId))
|
|
88
85
|
// if new node is within the storageRedundancyFactor closest nodes to the data
|
|
89
86
|
// do replicate data to it
|
|
90
87
|
if (index < this.config.redundancyFactor) {
|
|
@@ -92,8 +89,8 @@ export class StoreManager {
|
|
|
92
89
|
await this.replicateDataToContact(dataEntry, newNode)
|
|
93
90
|
})
|
|
94
91
|
}
|
|
95
|
-
} else if (!this.selfIsWithinRedundancyFactor(dataEntry.key)) {
|
|
96
|
-
this.config.localDataStore.setStale(dataEntry.key,
|
|
92
|
+
} else if (!this.selfIsWithinRedundancyFactor(getDhtAddressFromRaw(dataEntry.key))) {
|
|
93
|
+
this.config.localDataStore.setStale(getDhtAddressFromRaw(dataEntry.key), getDhtAddressFromRaw(dataEntry.creator), true)
|
|
97
94
|
}
|
|
98
95
|
}
|
|
99
96
|
|
|
@@ -106,7 +103,7 @@ export class StoreManager {
|
|
|
106
103
|
}
|
|
107
104
|
}
|
|
108
105
|
|
|
109
|
-
public async storeDataToDht(key:
|
|
106
|
+
public async storeDataToDht(key: DhtAddress, data: Any, creator: DhtAddress): Promise<PeerDescriptor[]> {
|
|
110
107
|
logger.debug(`Storing data to DHT ${this.config.serviceId}`)
|
|
111
108
|
const result = await this.config.recursiveOperationManager.execute(key, RecursiveOperation.FIND_NODE)
|
|
112
109
|
const closestNodes = result.closestNodes
|
|
@@ -116,9 +113,9 @@ export class StoreManager {
|
|
|
116
113
|
for (let i = 0; i < closestNodes.length && successfulNodes.length < this.config.redundancyFactor; i++) {
|
|
117
114
|
if (areEqualPeerDescriptors(this.config.localPeerDescriptor, closestNodes[i])) {
|
|
118
115
|
this.config.localDataStore.storeEntry({
|
|
119
|
-
key,
|
|
116
|
+
key: getRawFromDhtAddress(key),
|
|
120
117
|
data,
|
|
121
|
-
creator:
|
|
118
|
+
creator: getRawFromDhtAddress(creator),
|
|
122
119
|
createdAt,
|
|
123
120
|
storedAt: Timestamp.now(),
|
|
124
121
|
ttl,
|
|
@@ -131,9 +128,9 @@ export class StoreManager {
|
|
|
131
128
|
const rpcRemote = this.config.createRpcRemote(closestNodes[i])
|
|
132
129
|
try {
|
|
133
130
|
await rpcRemote.storeData({
|
|
134
|
-
key,
|
|
131
|
+
key: getRawFromDhtAddress(key),
|
|
135
132
|
data,
|
|
136
|
-
creator:
|
|
133
|
+
creator: getRawFromDhtAddress(creator),
|
|
137
134
|
createdAt,
|
|
138
135
|
ttl
|
|
139
136
|
})
|
|
@@ -146,22 +143,21 @@ export class StoreManager {
|
|
|
146
143
|
return successfulNodes
|
|
147
144
|
}
|
|
148
145
|
|
|
149
|
-
private selfIsWithinRedundancyFactor(dataKey:
|
|
146
|
+
private selfIsWithinRedundancyFactor(dataKey: DhtAddress): boolean {
|
|
150
147
|
const closestNeighbors = this.config.getClosestNeighborsTo(dataKey, this.config.redundancyFactor)
|
|
151
148
|
if (closestNeighbors.length < this.config.redundancyFactor) {
|
|
152
149
|
return true
|
|
153
150
|
} else {
|
|
154
|
-
const
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
return getDistance(dataId, localNodeId) < getDistance(dataId, furthestCloseNeighbor)
|
|
151
|
+
const furthestCloseNeighbor = closestNeighbors[closestNeighbors.length - 1]
|
|
152
|
+
const dataKeyRaw = getRawFromDhtAddress(dataKey)
|
|
153
|
+
return getDistance(dataKeyRaw, this.config.localPeerDescriptor.nodeId) < getDistance(dataKeyRaw, furthestCloseNeighbor.nodeId)
|
|
158
154
|
}
|
|
159
155
|
}
|
|
160
156
|
|
|
161
157
|
private async replicateDataToClosestNodes(): Promise<void> {
|
|
162
158
|
const dataEntries = Array.from(this.config.localDataStore.values())
|
|
163
159
|
await Promise.all(dataEntries.map(async (dataEntry) => {
|
|
164
|
-
const neighbors = this.config.getClosestNeighborsTo(dataEntry.key, this.config.redundancyFactor)
|
|
160
|
+
const neighbors = this.config.getClosestNeighborsTo(getDhtAddressFromRaw(dataEntry.key), this.config.redundancyFactor)
|
|
165
161
|
await Promise.all(neighbors.map(async (neighbor) => {
|
|
166
162
|
const rpcRemote = this.config.createRpcRemote(neighbor)
|
|
167
163
|
try {
|
|
@@ -178,9 +174,9 @@ export class StoreManager {
|
|
|
178
174
|
const localNodeId = getNodeIdFromPeerDescriptor(this.config.localPeerDescriptor)
|
|
179
175
|
const incomingNodeId = getNodeIdFromPeerDescriptor(incomingPeer)
|
|
180
176
|
// TODO use config option or named constant?
|
|
181
|
-
const closestToData = this.config.getClosestNeighborsTo(dataEntry.key, 10)
|
|
177
|
+
const closestToData = this.config.getClosestNeighborsTo(getDhtAddressFromRaw(dataEntry.key), 10)
|
|
182
178
|
const sortedList = new SortedContactList<Contact>({
|
|
183
|
-
referenceId:
|
|
179
|
+
referenceId: getDhtAddressFromRaw(dataEntry.key),
|
|
184
180
|
maxSize: this.config.redundancyFactor,
|
|
185
181
|
allowToContainReferenceId: true,
|
|
186
182
|
emitEvents: false
|
|
@@ -189,7 +185,7 @@ export class StoreManager {
|
|
|
189
185
|
closestToData.forEach((neighbor) => {
|
|
190
186
|
sortedList.addContact(new Contact(neighbor))
|
|
191
187
|
})
|
|
192
|
-
const selfIsPrimaryStorer =
|
|
188
|
+
const selfIsPrimaryStorer = (sortedList.getClosestContactId() === localNodeId)
|
|
193
189
|
const targets = selfIsPrimaryStorer
|
|
194
190
|
// if we are the closest to the data, replicate to all storageRedundancyFactor nearest
|
|
195
191
|
? sortedList.getAllContacts()
|
|
@@ -197,7 +193,7 @@ export class StoreManager {
|
|
|
197
193
|
: [sortedList.getAllContacts()[0]]
|
|
198
194
|
targets.forEach((contact) => {
|
|
199
195
|
const contactNodeId = getNodeIdFromPeerDescriptor(contact.getPeerDescriptor())
|
|
200
|
-
if (
|
|
196
|
+
if ((incomingNodeId !== contactNodeId) && (localNodeId !== contactNodeId)) {
|
|
201
197
|
setImmediate(() => {
|
|
202
198
|
executeSafePromise(async () => {
|
|
203
199
|
await this.replicateDataToContact(dataEntry, contact.getPeerDescriptor())
|
|
@@ -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:
|
|
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
|
|
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
|
-
|
|
59
|
-
|
|
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 {
|
package/src/helpers/PeerID.ts
CHANGED
|
@@ -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 {
|
|
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)
|
|
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():
|
|
80
|
-
return
|
|
79
|
+
toNodeId(): DhtAddress {
|
|
80
|
+
return getDhtAddressFromRaw(this.data)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
get value(): Uint8Array {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { areEqualBinaries
|
|
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 {
|
|
4
|
+
import { DhtAddress, getDhtAddressFromRaw } from '../identifiers'
|
|
5
5
|
|
|
6
6
|
export const peerIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): PeerID => {
|
|
7
7
|
return PeerID.fromValue(peerDescriptor.nodeId)
|
|
@@ -9,8 +9,8 @@ export const peerIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): PeerID
|
|
|
9
9
|
|
|
10
10
|
// TODO could use this in trackerless-network (instead of copy-pasted same implementation)
|
|
11
11
|
// and move this to nodeId.ts
|
|
12
|
-
export const getNodeIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor):
|
|
13
|
-
return
|
|
12
|
+
export const getNodeIdFromPeerDescriptor = (peerDescriptor: PeerDescriptor): DhtAddress => {
|
|
13
|
+
return getDhtAddressFromRaw(peerDescriptor.nodeId)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
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:
|
|
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):
|
|
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 {
|
|
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<
|
|
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
|
}
|
|
@@ -3,19 +3,20 @@
|
|
|
3
3
|
import KBucket from 'k-bucket'
|
|
4
4
|
import { SortedContactList } from '../../src/dht/contact/SortedContactList'
|
|
5
5
|
import crypto from 'crypto'
|
|
6
|
-
import {
|
|
6
|
+
import { DhtAddress, DhtAddressRaw, getDhtAddressFromRaw } from '../../src/identifiers'
|
|
7
7
|
|
|
8
8
|
const NUM_ADDS = 1000
|
|
9
|
+
|
|
9
10
|
interface Item {
|
|
10
|
-
id:
|
|
11
|
+
id: DhtAddressRaw
|
|
11
12
|
vectorClock: number
|
|
12
|
-
getNodeId: () =>
|
|
13
|
+
getNodeId: () => DhtAddress
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const createRandomItem = (index: number): Item => {
|
|
16
17
|
const rand = new Uint8Array(crypto.randomBytes(20))
|
|
17
18
|
return {
|
|
18
|
-
getNodeId: () =>
|
|
19
|
+
getNodeId: () => getDhtAddressFromRaw(rand),
|
|
19
20
|
id: rand,
|
|
20
21
|
vectorClock: index
|
|
21
22
|
}
|
|
@@ -37,7 +38,7 @@ describe('SortedContactListBenchmark', () => {
|
|
|
37
38
|
randomIds.push(createRandomItem(i))
|
|
38
39
|
}
|
|
39
40
|
const list = new SortedContactList({
|
|
40
|
-
referenceId:
|
|
41
|
+
referenceId: getDhtAddressFromRaw(crypto.randomBytes(20)),
|
|
41
42
|
allowToContainReferenceId: true,
|
|
42
43
|
emitEvents: true
|
|
43
44
|
})
|
|
@@ -49,7 +50,7 @@ describe('SortedContactListBenchmark', () => {
|
|
|
49
50
|
console.timeEnd('SortedContactList.addContact() with emitEvents=true')
|
|
50
51
|
|
|
51
52
|
const list2 = new SortedContactList({
|
|
52
|
-
referenceId:
|
|
53
|
+
referenceId: getDhtAddressFromRaw(crypto.randomBytes(20)),
|
|
53
54
|
allowToContainReferenceId: true,
|
|
54
55
|
emitEvents: false
|
|
55
56
|
})
|
|
@@ -83,13 +84,13 @@ describe('SortedContactListBenchmark', () => {
|
|
|
83
84
|
console.time('SortedContactList.getClosestContacts() with emitEvents=true')
|
|
84
85
|
for (let i = 0; i < NUM_ADDS; i++) {
|
|
85
86
|
const closest = new SortedContactList<Item>({
|
|
86
|
-
referenceId:
|
|
87
|
+
referenceId: getDhtAddressFromRaw(crypto.randomBytes(20)),
|
|
87
88
|
allowToContainReferenceId: true,
|
|
88
89
|
emitEvents: true
|
|
89
90
|
})
|
|
90
91
|
|
|
91
92
|
const arrayFromBucket = kBucket.toArray()
|
|
92
|
-
arrayFromBucket.
|
|
93
|
+
arrayFromBucket.forEach((contact) => closest.addContact(contact))
|
|
93
94
|
closest.getClosestContacts(20)
|
|
94
95
|
}
|
|
95
96
|
console.timeEnd('SortedContactList.getClosestContacts() with emitEvents=true')
|
|
@@ -97,13 +98,13 @@ describe('SortedContactListBenchmark', () => {
|
|
|
97
98
|
console.time('SortedContactList.getClosestContacts() with emitEvents=false')
|
|
98
99
|
for (let i = 0; i < NUM_ADDS; i++) {
|
|
99
100
|
const closest = new SortedContactList<Item>({
|
|
100
|
-
referenceId:
|
|
101
|
+
referenceId: getDhtAddressFromRaw(crypto.randomBytes(20)),
|
|
101
102
|
allowToContainReferenceId: true,
|
|
102
103
|
emitEvents: false
|
|
103
104
|
})
|
|
104
105
|
|
|
105
106
|
const arrayFromBucket = kBucket.toArray()
|
|
106
|
-
arrayFromBucket.
|
|
107
|
+
arrayFromBucket.forEach((contact) => closest.addContact(contact))
|
|
107
108
|
closest.getClosestContacts(20)
|
|
108
109
|
}
|
|
109
110
|
console.timeEnd('SortedContactList.getClosestContacts() with emitEvents=false')
|
|
@@ -111,13 +112,13 @@ describe('SortedContactListBenchmark', () => {
|
|
|
111
112
|
console.time('SortedContactList.getClosestContacts() with emitEvents=false and lodash')
|
|
112
113
|
for (let i = 0; i < NUM_ADDS; i++) {
|
|
113
114
|
const closest = new SortedContactList<Item>({
|
|
114
|
-
referenceId:
|
|
115
|
+
referenceId: getDhtAddressFromRaw(crypto.randomBytes(20)),
|
|
115
116
|
allowToContainReferenceId: true,
|
|
116
117
|
emitEvents: false
|
|
117
118
|
})
|
|
118
119
|
|
|
119
120
|
const arrayFromBucket = kBucket.toArray()
|
|
120
|
-
arrayFromBucket.
|
|
121
|
+
arrayFromBucket.forEach((contact) => closest.addContact(contact))
|
|
121
122
|
closest.getClosestContacts(20)
|
|
122
123
|
}
|
|
123
124
|
console.timeEnd('SortedContactList.getClosestContacts() with emitEvents=false and lodash')
|
|
@@ -125,7 +126,7 @@ describe('SortedContactListBenchmark', () => {
|
|
|
125
126
|
console.time('SortedContactList.getClosestContacts() with emitEvents=false and addContacts()')
|
|
126
127
|
for (let i = 0; i < NUM_ADDS; i++) {
|
|
127
128
|
const closest = new SortedContactList<Item>({
|
|
128
|
-
referenceId:
|
|
129
|
+
referenceId: getDhtAddressFromRaw(crypto.randomBytes(20)),
|
|
129
130
|
allowToContainReferenceId: true,
|
|
130
131
|
emitEvents: false
|
|
131
132
|
})
|
|
@@ -141,7 +142,7 @@ describe('SortedContactListBenchmark', () => {
|
|
|
141
142
|
for (let i = 0; i < NUM_ADDS; i++) {
|
|
142
143
|
const bucket2 = new KBucket<Item>({ localNodeId: crypto.randomBytes(20) })
|
|
143
144
|
|
|
144
|
-
shuffled.
|
|
145
|
+
shuffled.forEach((contact) => bucket2.add(contact))
|
|
145
146
|
bucket2.closest(crypto.randomBytes(20), 20)
|
|
146
147
|
}
|
|
147
148
|
console.timeEnd('kbucket add and closest')
|
|
@@ -1,32 +1,31 @@
|
|
|
1
1
|
import type { SimulationNode } from './SimulationNode'
|
|
2
2
|
import { NodeType, PeerDescriptor } from '../../../src/proto/packages/dht/protos/DhtRpc'
|
|
3
|
-
import {
|
|
4
|
-
import { hexToBinary } from '@streamr/utils'
|
|
3
|
+
import { DhtAddress, DhtAddressRaw, getRawFromDhtAddress } from '../../../src/identifiers'
|
|
5
4
|
|
|
6
5
|
export class Contact {
|
|
7
6
|
private static counter = 0
|
|
8
7
|
|
|
9
|
-
public ownId:
|
|
10
|
-
public id:
|
|
8
|
+
public ownId: DhtAddress
|
|
9
|
+
public id: DhtAddressRaw
|
|
11
10
|
public vectorClock = 0
|
|
12
11
|
public dhtNode: SimulationNode | undefined
|
|
13
12
|
|
|
14
|
-
constructor(ownId:
|
|
13
|
+
constructor(ownId: DhtAddress, dhtNode?: SimulationNode) {
|
|
15
14
|
this.ownId = ownId
|
|
16
15
|
this.vectorClock = Contact.counter++
|
|
17
16
|
this.dhtNode = dhtNode
|
|
18
|
-
this.id =
|
|
17
|
+
this.id = getRawFromDhtAddress(ownId)
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
getPeerDescriptor(): PeerDescriptor {
|
|
22
21
|
const peerDescriptor: PeerDescriptor = {
|
|
23
|
-
nodeId:
|
|
22
|
+
nodeId: getRawFromDhtAddress(this.ownId),
|
|
24
23
|
type: NodeType.NODEJS
|
|
25
24
|
}
|
|
26
25
|
return peerDescriptor
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
getNodeId():
|
|
28
|
+
getNodeId(): DhtAddress {
|
|
30
29
|
return this.ownId
|
|
31
30
|
}
|
|
32
31
|
|