@libp2p/kad-dht 12.0.15 → 12.0.16
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/index.min.js +4 -4
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +1 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/content-routing/index.d.ts.map +1 -1
- package/dist/src/content-routing/index.js +3 -2
- package/dist/src/content-routing/index.js.map +1 -1
- package/dist/src/index.d.ts +34 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/network.d.ts +3 -0
- package/dist/src/network.d.ts.map +1 -1
- package/dist/src/network.js +33 -8
- package/dist/src/network.js.map +1 -1
- package/dist/src/peer-list/peer-distance-list.d.ts +13 -4
- package/dist/src/peer-list/peer-distance-list.d.ts.map +1 -1
- package/dist/src/peer-list/peer-distance-list.js +29 -21
- package/dist/src/peer-list/peer-distance-list.js.map +1 -1
- package/dist/src/peer-routing/index.d.ts +5 -5
- package/dist/src/peer-routing/index.d.ts.map +1 -1
- package/dist/src/peer-routing/index.js +15 -24
- package/dist/src/peer-routing/index.js.map +1 -1
- package/dist/src/query/manager.d.ts +3 -0
- package/dist/src/query/manager.d.ts.map +1 -1
- package/dist/src/query/manager.js +14 -5
- package/dist/src/query/manager.js.map +1 -1
- package/dist/src/query/query-path.d.ts +6 -6
- package/dist/src/query/query-path.d.ts.map +1 -1
- package/dist/src/query/query-path.js +32 -20
- package/dist/src/query/query-path.js.map +1 -1
- package/dist/src/routing-table/index.d.ts +11 -5
- package/dist/src/routing-table/index.d.ts.map +1 -1
- package/dist/src/routing-table/index.js +84 -42
- package/dist/src/routing-table/index.js.map +1 -1
- package/dist/src/routing-table/k-bucket.d.ts +80 -115
- package/dist/src/routing-table/k-bucket.d.ts.map +1 -1
- package/dist/src/routing-table/k-bucket.js +165 -311
- package/dist/src/routing-table/k-bucket.js.map +1 -1
- package/dist/src/routing-table/refresh.d.ts.map +1 -1
- package/dist/src/routing-table/refresh.js +9 -4
- package/dist/src/routing-table/refresh.js.map +1 -1
- package/package.json +8 -10
- package/src/constants.ts +1 -1
- package/src/content-routing/index.ts +3 -2
- package/src/index.ts +37 -1
- package/src/network.ts +38 -9
- package/src/peer-list/peer-distance-list.ts +36 -25
- package/src/peer-routing/index.ts +19 -28
- package/src/query/manager.ts +18 -5
- package/src/query/query-path.ts +46 -30
- package/src/routing-table/index.ts +100 -46
- package/src/routing-table/k-bucket.ts +214 -359
- package/src/routing-table/refresh.ts +10 -4
- package/dist/src/query/utils.d.ts +0 -6
- package/dist/src/query/utils.d.ts.map +0 -1
- package/dist/src/query/utils.js +0 -53
- package/dist/src/query/utils.js.map +0 -1
- package/src/query/utils.ts +0 -64
|
@@ -1,32 +1,9 @@
|
|
|
1
|
-
/*
|
|
2
|
-
index.js - Kademlia DHT K-bucket implementation as a binary tree.
|
|
3
|
-
|
|
4
|
-
The MIT License (MIT)
|
|
5
|
-
|
|
6
|
-
Copyright (c) 2013-2021 Tristan Slominski
|
|
7
|
-
|
|
8
|
-
Permission is hereby granted, free of charge, to any person
|
|
9
|
-
obtaining a copy of this software and associated documentation
|
|
10
|
-
files (the "Software"), to deal in the Software without
|
|
11
|
-
restriction, including without limitation the rights to use,
|
|
12
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
-
copies of the Software, and to permit persons to whom the
|
|
14
|
-
Software is furnished to do so, subject to the following
|
|
15
|
-
conditions:
|
|
16
|
-
|
|
17
|
-
The above copyright notice and this permission notice shall be
|
|
18
|
-
included in all copies or substantial portions of the Software.
|
|
19
|
-
|
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
21
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
22
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
23
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
24
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
25
|
-
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
26
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
27
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
|
28
|
-
*/
|
|
29
1
|
import { TypedEventEmitter } from '@libp2p/interface';
|
|
2
|
+
import map from 'it-map';
|
|
3
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
|
|
4
|
+
import { xor as uint8ArrayXor } from 'uint8arrays/xor';
|
|
5
|
+
import { PeerDistanceList } from '../peer-list/peer-distance-list.js';
|
|
6
|
+
import { KBUCKET_SIZE } from './index.js';
|
|
30
7
|
function arrayEquals(array1, array2) {
|
|
31
8
|
if (array1 === array2) {
|
|
32
9
|
return true;
|
|
@@ -41,150 +18,96 @@ function arrayEquals(array1, array2) {
|
|
|
41
18
|
}
|
|
42
19
|
return true;
|
|
43
20
|
}
|
|
44
|
-
function createNode() {
|
|
45
|
-
// @ts-expect-error loose types
|
|
46
|
-
return { contacts: [], dontSplit: false, left: null, right: null };
|
|
47
|
-
}
|
|
48
21
|
function ensureInt8(name, val) {
|
|
49
22
|
if (!(val instanceof Uint8Array)) {
|
|
50
23
|
throw new TypeError(name + ' is not a Uint8Array');
|
|
51
24
|
}
|
|
25
|
+
if (val.byteLength !== 32) {
|
|
26
|
+
throw new TypeError(name + ' had incorrect length');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function isLeafBucket(obj) {
|
|
30
|
+
return Array.isArray(obj?.peers);
|
|
52
31
|
}
|
|
53
32
|
/**
|
|
54
|
-
* Implementation of a Kademlia DHT
|
|
55
|
-
*
|
|
33
|
+
* Implementation of a Kademlia DHT routing table as a prefix binary trie with
|
|
34
|
+
* configurable prefix length, bucket split threshold and size.
|
|
56
35
|
*/
|
|
57
36
|
export class KBucket extends TypedEventEmitter {
|
|
58
|
-
localNodeId;
|
|
59
37
|
root;
|
|
60
|
-
|
|
38
|
+
localPeer;
|
|
39
|
+
prefixLength;
|
|
40
|
+
splitThreshold;
|
|
41
|
+
kBucketSize;
|
|
61
42
|
numberOfNodesToPing;
|
|
62
|
-
distance;
|
|
63
|
-
arbiter;
|
|
64
43
|
constructor(options) {
|
|
65
44
|
super();
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
45
|
+
this.localPeer = options.localPeer;
|
|
46
|
+
this.prefixLength = options.prefixLength;
|
|
47
|
+
this.kBucketSize = options.kBucketSize ?? KBUCKET_SIZE;
|
|
48
|
+
this.splitThreshold = options.splitThreshold ?? this.kBucketSize;
|
|
68
49
|
this.numberOfNodesToPing = options.numberOfNodesToPing ?? 3;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Default arbiter function for contacts with the same id. Uses
|
|
77
|
-
* contact.vectorClock to select which contact to update the k-bucket with.
|
|
78
|
-
* Contact with larger vectorClock field will be selected. If vectorClock is
|
|
79
|
-
* the same, candidate will be selected.
|
|
80
|
-
*
|
|
81
|
-
* @param {object} incumbent - Contact currently stored in the k-bucket.
|
|
82
|
-
* @param {object} candidate - Contact being added to the k-bucket.
|
|
83
|
-
* @returns {object} Contact to updated the k-bucket with.
|
|
84
|
-
*/
|
|
85
|
-
static arbiter(incumbent, candidate) {
|
|
86
|
-
return (incumbent.vectorClock ?? 0) > (candidate.vectorClock ?? 0) ? incumbent : candidate;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Default distance function. Finds the XOR
|
|
90
|
-
* distance between firstId and secondId.
|
|
91
|
-
*
|
|
92
|
-
* @param {Uint8Array} firstId - Uint8Array containing first id.
|
|
93
|
-
* @param {Uint8Array} secondId - Uint8Array containing second id.
|
|
94
|
-
* @returns {number} Integer The XOR distance between firstId and secondId.
|
|
95
|
-
*/
|
|
96
|
-
static distance(firstId, secondId) {
|
|
97
|
-
let distance = 0;
|
|
98
|
-
let i = 0;
|
|
99
|
-
const min = Math.min(firstId.length, secondId.length);
|
|
100
|
-
const max = Math.max(firstId.length, secondId.length);
|
|
101
|
-
for (; i < min; ++i) {
|
|
102
|
-
distance = distance * 256 + (firstId[i] ^ secondId[i]);
|
|
103
|
-
}
|
|
104
|
-
for (; i < max; ++i)
|
|
105
|
-
distance = distance * 256 + 255;
|
|
106
|
-
return distance;
|
|
50
|
+
ensureInt8('options.localPeer.kadId', options.localPeer.kadId);
|
|
51
|
+
this.root = {
|
|
52
|
+
prefix: '',
|
|
53
|
+
depth: 0,
|
|
54
|
+
peers: []
|
|
55
|
+
};
|
|
107
56
|
}
|
|
108
57
|
/**
|
|
109
58
|
* Adds a contact to the k-bucket.
|
|
110
59
|
*
|
|
111
|
-
* @param {
|
|
60
|
+
* @param {Peer} peer - the contact object to add
|
|
112
61
|
*/
|
|
113
|
-
add(
|
|
114
|
-
ensureInt8('
|
|
115
|
-
|
|
116
|
-
let node = this.root;
|
|
117
|
-
while (node.contacts === null) {
|
|
118
|
-
// this is not a leaf node but an inner node with 'low' and 'high'
|
|
119
|
-
// branches; we will check the appropriate bit of the identifier and
|
|
120
|
-
// delegate to the appropriate node for further processing
|
|
121
|
-
node = this._determineNode(node, contact.id, bitIndex++);
|
|
122
|
-
}
|
|
62
|
+
add(peer) {
|
|
63
|
+
ensureInt8('peer.kadId', peer?.kadId);
|
|
64
|
+
const bucket = this._determineBucket(peer.kadId);
|
|
123
65
|
// check if the contact already exists
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this._update(node, index, contact);
|
|
127
|
-
return this;
|
|
66
|
+
if (this._indexOf(bucket, peer.kadId) > -1) {
|
|
67
|
+
return;
|
|
128
68
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
69
|
+
// are there too many peers in the bucket and can we make the trie deeper?
|
|
70
|
+
if (bucket.peers.length === this.splitThreshold && bucket.depth < this.prefixLength) {
|
|
71
|
+
// split the bucket
|
|
72
|
+
this._split(bucket);
|
|
73
|
+
// try again
|
|
74
|
+
this.add(peer);
|
|
75
|
+
return;
|
|
133
76
|
}
|
|
134
|
-
// the bucket
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// only if one of the pinged nodes does not respond, can the new contact
|
|
140
|
-
// be added (this prevents DoS flodding with new invalid contacts)
|
|
141
|
-
this.safeDispatchEvent('ping', {
|
|
142
|
-
detail: {
|
|
143
|
-
oldContacts: node.contacts.slice(0, this.numberOfNodesToPing),
|
|
144
|
-
newContact: contact
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
return this;
|
|
77
|
+
// is there space in the bucket?
|
|
78
|
+
if (bucket.peers.length < this.kBucketSize) {
|
|
79
|
+
bucket.peers.push(peer);
|
|
80
|
+
this.safeDispatchEvent('added', { detail: peer });
|
|
81
|
+
return;
|
|
148
82
|
}
|
|
149
|
-
|
|
150
|
-
|
|
83
|
+
// we are at the bottom of the trie and the bucket is full so we can't add
|
|
84
|
+
// any more peers.
|
|
85
|
+
//
|
|
86
|
+
// instead ping the first this.numberOfNodesToPing in order to determine
|
|
87
|
+
// if they are still online.
|
|
88
|
+
//
|
|
89
|
+
// only add the new peer if one of the pinged nodes does not respond, this
|
|
90
|
+
// prevents DoS flooding with new invalid contacts.
|
|
91
|
+
this.safeDispatchEvent('ping', {
|
|
92
|
+
detail: {
|
|
93
|
+
oldContacts: bucket.peers.slice(0, this.numberOfNodesToPing),
|
|
94
|
+
newContact: peer
|
|
95
|
+
}
|
|
96
|
+
});
|
|
151
97
|
}
|
|
152
98
|
/**
|
|
153
|
-
* Get
|
|
99
|
+
* Get 0-n closest contacts to the provided node id. "Closest" here means:
|
|
154
100
|
* closest according to the XOR metric of the contact node id.
|
|
155
101
|
*
|
|
156
102
|
* @param {Uint8Array} id - Contact node id
|
|
157
|
-
* @
|
|
158
|
-
* @returns {Array} Array Maximum of n closest contacts to the node id
|
|
103
|
+
* @returns {Generator<Peer, void, undefined>} Array Maximum of n closest contacts to the node id
|
|
159
104
|
*/
|
|
160
|
-
closest(id, n =
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
let contacts = [];
|
|
166
|
-
for (let nodes = [this.root], bitIndex = 0; nodes.length > 0 && contacts.length < n;) {
|
|
167
|
-
const node = nodes.pop();
|
|
168
|
-
if (node == null) {
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
if (node.contacts === null) {
|
|
172
|
-
const detNode = this._determineNode(node, id, bitIndex++);
|
|
173
|
-
nodes.push(node.left === detNode ? node.right : node.left);
|
|
174
|
-
nodes.push(detNode);
|
|
175
|
-
}
|
|
176
|
-
else {
|
|
177
|
-
contacts = contacts.concat(node.contacts);
|
|
178
|
-
}
|
|
105
|
+
*closest(id, n = this.kBucketSize) {
|
|
106
|
+
const list = new PeerDistanceList(id, n);
|
|
107
|
+
for (const peer of this.toIterable()) {
|
|
108
|
+
list.addWitKadId({ id: peer.peerId, multiaddrs: [] }, peer.kadId);
|
|
179
109
|
}
|
|
180
|
-
|
|
181
|
-
.map(a => ({
|
|
182
|
-
distance: this.distance(a.id, id),
|
|
183
|
-
contact: a
|
|
184
|
-
}))
|
|
185
|
-
.sort((a, b) => a.distance - b.distance)
|
|
186
|
-
.slice(0, n)
|
|
187
|
-
.map(a => a.contact);
|
|
110
|
+
yield* map(list.peers, info => info.id);
|
|
188
111
|
}
|
|
189
112
|
/**
|
|
190
113
|
* Counts the total number of contacts in the tree.
|
|
@@ -192,58 +115,20 @@ export class KBucket extends TypedEventEmitter {
|
|
|
192
115
|
* @returns {number} The number of contacts held in the tree
|
|
193
116
|
*/
|
|
194
117
|
count() {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const node = nodes.pop();
|
|
199
|
-
if (node == null) {
|
|
200
|
-
continue;
|
|
118
|
+
function countBucket(bucket) {
|
|
119
|
+
if (isLeafBucket(bucket)) {
|
|
120
|
+
return bucket.peers.length;
|
|
201
121
|
}
|
|
202
|
-
|
|
203
|
-
|
|
122
|
+
let count = 0;
|
|
123
|
+
if (bucket.left != null) {
|
|
124
|
+
count += countBucket(bucket.left);
|
|
204
125
|
}
|
|
205
|
-
|
|
206
|
-
count +=
|
|
126
|
+
if (bucket.right != null) {
|
|
127
|
+
count += countBucket(bucket.right);
|
|
207
128
|
}
|
|
129
|
+
return count;
|
|
208
130
|
}
|
|
209
|
-
return
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Determines whether the id at the bitIndex is 0 or 1.
|
|
213
|
-
* Return left leaf if `id` at `bitIndex` is 0, right leaf otherwise
|
|
214
|
-
*
|
|
215
|
-
* @param {object} node - internal object that has 2 leafs: left and right
|
|
216
|
-
* @param {Uint8Array} id - Id to compare localNodeId with.
|
|
217
|
-
* @param {number} bitIndex - Integer (Default: 0) The bit index to which bit to check in the id Uint8Array.
|
|
218
|
-
* @returns {object} left leaf if id at bitIndex is 0, right leaf otherwise.
|
|
219
|
-
*/
|
|
220
|
-
_determineNode(node, id, bitIndex) {
|
|
221
|
-
// **NOTE** remember that id is a Uint8Array and has granularity of
|
|
222
|
-
// bytes (8 bits), whereas the bitIndex is the _bit_ index (not byte)
|
|
223
|
-
// id's that are too short are put in low bucket (1 byte = 8 bits)
|
|
224
|
-
// (bitIndex >> 3) finds how many bytes the bitIndex describes
|
|
225
|
-
// bitIndex % 8 checks if we have extra bits beyond byte multiples
|
|
226
|
-
// if number of bytes is <= no. of bytes described by bitIndex and there
|
|
227
|
-
// are extra bits to consider, this means id has less bits than what
|
|
228
|
-
// bitIndex describes, id therefore is too short, and will be put in low
|
|
229
|
-
// bucket
|
|
230
|
-
const bytesDescribedByBitIndex = bitIndex >> 3;
|
|
231
|
-
const bitIndexWithinByte = bitIndex % 8;
|
|
232
|
-
if ((id.length <= bytesDescribedByBitIndex) && (bitIndexWithinByte !== 0)) {
|
|
233
|
-
return node.left;
|
|
234
|
-
}
|
|
235
|
-
const byteUnderConsideration = id[bytesDescribedByBitIndex];
|
|
236
|
-
// byteUnderConsideration is an integer from 0 to 255 represented by 8 bits
|
|
237
|
-
// where 255 is 11111111 and 0 is 00000000
|
|
238
|
-
// in order to find out whether the bit at bitIndexWithinByte is set
|
|
239
|
-
// we construct (1 << (7 - bitIndexWithinByte)) which will consist
|
|
240
|
-
// of all bits being 0, with only one bit set to 1
|
|
241
|
-
// for example, if bitIndexWithinByte is 3, we will construct 00010000 by
|
|
242
|
-
// (1 << (7 - 3)) -> (1 << 4) -> 16
|
|
243
|
-
if ((byteUnderConsideration & (1 << (7 - bitIndexWithinByte))) !== 0) {
|
|
244
|
-
return node.right;
|
|
245
|
-
}
|
|
246
|
-
return node.left;
|
|
131
|
+
return countBucket(this.root);
|
|
247
132
|
}
|
|
248
133
|
/**
|
|
249
134
|
* Get a contact by its exact ID.
|
|
@@ -251,157 +136,126 @@ export class KBucket extends TypedEventEmitter {
|
|
|
251
136
|
* contact if we have it or null if not. If this is an inner node, determine
|
|
252
137
|
* which branch of the tree to traverse and repeat.
|
|
253
138
|
*
|
|
254
|
-
* @param {Uint8Array}
|
|
255
|
-
* @returns {object |
|
|
139
|
+
* @param {Uint8Array} kadId - The ID of the contact to fetch.
|
|
140
|
+
* @returns {object | undefined} The contact if available, otherwise null
|
|
256
141
|
*/
|
|
257
|
-
get(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
while (node.contacts === null) {
|
|
262
|
-
node = this._determineNode(node, id, bitIndex++);
|
|
263
|
-
}
|
|
264
|
-
// index of uses contact id for matching
|
|
265
|
-
const index = this._indexOf(node, id);
|
|
266
|
-
return index >= 0 ? node.contacts[index] : undefined;
|
|
142
|
+
get(kadId) {
|
|
143
|
+
const bucket = this._determineBucket(kadId);
|
|
144
|
+
const index = this._indexOf(bucket, kadId);
|
|
145
|
+
return bucket.peers[index];
|
|
267
146
|
}
|
|
268
147
|
/**
|
|
269
|
-
*
|
|
270
|
-
* id if it exists, returns -1 otherwise.
|
|
148
|
+
* Removes contact with the provided id.
|
|
271
149
|
*
|
|
272
|
-
* @param {
|
|
273
|
-
* @param {Uint8Array} id - Contact node id.
|
|
274
|
-
* @returns {number} Integer Index of contact with provided id if it exists, -1 otherwise.
|
|
150
|
+
* @param {Uint8Array} kadId - The ID of the contact to remove
|
|
275
151
|
*/
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
152
|
+
remove(kadId) {
|
|
153
|
+
const bucket = this._determineBucket(kadId);
|
|
154
|
+
const index = this._indexOf(bucket, kadId);
|
|
155
|
+
if (index > -1) {
|
|
156
|
+
const peer = bucket.peers.splice(index, 1)[0];
|
|
157
|
+
this.safeDispatchEvent('removed', {
|
|
158
|
+
detail: peer
|
|
159
|
+
});
|
|
280
160
|
}
|
|
281
|
-
return -1;
|
|
282
161
|
}
|
|
283
162
|
/**
|
|
284
|
-
*
|
|
163
|
+
* Similar to `toArray()` but instead of buffering everything up into an
|
|
164
|
+
* array before returning it, yields contacts as they are encountered while
|
|
165
|
+
* walking the tree.
|
|
285
166
|
*
|
|
286
|
-
* @
|
|
287
|
-
* @returns {object} The k-bucket itself
|
|
167
|
+
* @returns {Iterable} All of the contacts in the tree, as an iterable
|
|
288
168
|
*/
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (index >= 0) {
|
|
298
|
-
const contact = node.contacts.splice(index, 1)[0];
|
|
299
|
-
this.safeDispatchEvent('removed', {
|
|
300
|
-
detail: contact
|
|
301
|
-
});
|
|
169
|
+
*toIterable() {
|
|
170
|
+
function* iterate(bucket) {
|
|
171
|
+
if (isLeafBucket(bucket)) {
|
|
172
|
+
yield* bucket.peers;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
yield* iterate(bucket.left);
|
|
176
|
+
yield* iterate(bucket.right);
|
|
302
177
|
}
|
|
303
|
-
|
|
178
|
+
yield* iterate(this.root);
|
|
304
179
|
}
|
|
305
180
|
/**
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
* setting this.root.contacts = null
|
|
181
|
+
* Default distance function. Finds the XOR distance between firstId and
|
|
182
|
+
* secondId.
|
|
309
183
|
*
|
|
310
|
-
* @param
|
|
311
|
-
* @param
|
|
184
|
+
* @param {Uint8Array} firstId - Uint8Array containing first id.
|
|
185
|
+
* @param {Uint8Array} secondId - Uint8Array containing second id.
|
|
186
|
+
* @returns {number} Integer The XOR distance between firstId and secondId.
|
|
312
187
|
*/
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
node.right = createNode();
|
|
316
|
-
// redistribute existing contacts amongst the two newly created nodes
|
|
317
|
-
for (const contact of node.contacts) {
|
|
318
|
-
this._determineNode(node, contact.id, bitIndex).contacts.push(contact);
|
|
319
|
-
}
|
|
320
|
-
// @ts-expect-error loose types
|
|
321
|
-
node.contacts = null; // mark as inner tree node
|
|
322
|
-
// don't split the "far away" node
|
|
323
|
-
// we check where the local node would end up and mark the other one as
|
|
324
|
-
// "dontSplit" (i.e. "far away")
|
|
325
|
-
const detNode = this._determineNode(node, this.localNodeId, bitIndex);
|
|
326
|
-
const otherNode = node.left === detNode ? node.right : node.left;
|
|
327
|
-
otherNode.dontSplit = true;
|
|
188
|
+
distance(firstId, secondId) {
|
|
189
|
+
return BigInt('0x' + uint8ArrayToString(uint8ArrayXor(firstId, secondId), 'base16'));
|
|
328
190
|
}
|
|
329
191
|
/**
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
* return the union of the low and high branches (themselves also as arrays).
|
|
192
|
+
* Determines whether the id at the bitIndex is 0 or 1
|
|
193
|
+
* Return left leaf if `id` at `bitIndex` is 0, right leaf otherwise
|
|
333
194
|
*
|
|
334
|
-
* @
|
|
195
|
+
* @param {Uint8Array} kadId - Id to compare localNodeId with
|
|
196
|
+
* @returns {LeafBucket} left leaf if id at bitIndex is 0, right leaf otherwise.
|
|
335
197
|
*/
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
if (node.contacts === null) {
|
|
344
|
-
nodes.push(node.right, node.left);
|
|
198
|
+
_determineBucket(kadId) {
|
|
199
|
+
const bitString = uint8ArrayToString(kadId, 'base2');
|
|
200
|
+
const prefix = bitString.substring(0, this.prefixLength);
|
|
201
|
+
function findBucket(bucket, bitIndex = 0) {
|
|
202
|
+
if (isLeafBucket(bucket)) {
|
|
203
|
+
return bucket;
|
|
345
204
|
}
|
|
346
|
-
|
|
347
|
-
|
|
205
|
+
const bit = prefix[bitIndex];
|
|
206
|
+
if (bit === '0') {
|
|
207
|
+
return findBucket(bucket.left, bitIndex + 1);
|
|
348
208
|
}
|
|
209
|
+
return findBucket(bucket.right, bitIndex + 1);
|
|
349
210
|
}
|
|
350
|
-
return
|
|
211
|
+
return findBucket(this.root);
|
|
351
212
|
}
|
|
352
213
|
/**
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
* walking the tree.
|
|
214
|
+
* Returns the index of the contact with provided
|
|
215
|
+
* id if it exists, returns -1 otherwise.
|
|
356
216
|
*
|
|
357
|
-
* @
|
|
217
|
+
* @param {object} bucket - internal object that has 2 leafs: left and right
|
|
218
|
+
* @param {Uint8Array} kadId - KadId of peer
|
|
219
|
+
* @returns {number} Integer Index of contact with provided id if it exists, -1 otherwise.
|
|
358
220
|
*/
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const node = nodes.pop();
|
|
362
|
-
if (node == null) {
|
|
363
|
-
continue;
|
|
364
|
-
}
|
|
365
|
-
if (node.contacts === null) {
|
|
366
|
-
nodes.push(node.right, node.left);
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
yield* node.contacts;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
221
|
+
_indexOf(bucket, kadId) {
|
|
222
|
+
return bucket.peers.findIndex(peer => arrayEquals(peer.kadId, kadId));
|
|
372
223
|
}
|
|
373
224
|
/**
|
|
374
|
-
*
|
|
375
|
-
* If the selection is our old contact and the candidate is some new contact
|
|
376
|
-
* then the new contact is abandoned (not added).
|
|
377
|
-
* If the selection is our old contact and the candidate is our old contact
|
|
378
|
-
* then we are refreshing the contact and it is marked as most recently
|
|
379
|
-
* contacted (by being moved to the right/end of the bucket array).
|
|
380
|
-
* If the selection is our new contact, the old contact is removed and the new
|
|
381
|
-
* contact is marked as most recently contacted.
|
|
225
|
+
* Modify the bucket, turn it from a leaf bucket to an internal bucket
|
|
382
226
|
*
|
|
383
|
-
* @param {
|
|
384
|
-
* @param {number} index - the index in the bucket where contact exists (index has already been computed in a previous calculation)
|
|
385
|
-
* @param {object} contact - The contact object to update
|
|
227
|
+
* @param {any} bucket - bucket for splitting
|
|
386
228
|
*/
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
229
|
+
_split(bucket) {
|
|
230
|
+
const depth = bucket.depth + 1;
|
|
231
|
+
// create child buckets
|
|
232
|
+
const left = {
|
|
233
|
+
prefix: '0',
|
|
234
|
+
depth,
|
|
235
|
+
peers: []
|
|
236
|
+
};
|
|
237
|
+
const right = {
|
|
238
|
+
prefix: '1',
|
|
239
|
+
depth,
|
|
240
|
+
peers: []
|
|
241
|
+
};
|
|
242
|
+
// redistribute peers
|
|
243
|
+
for (const peer of bucket.peers) {
|
|
244
|
+
const bitString = uint8ArrayToString(peer.kadId, 'base2');
|
|
245
|
+
if (bitString[depth] === '0') {
|
|
246
|
+
left.peers.push(peer);
|
|
403
247
|
}
|
|
404
|
-
|
|
248
|
+
else {
|
|
249
|
+
right.peers.push(peer);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
// convert leaf bucket to internal bucket
|
|
253
|
+
// @ts-expect-error peers is not a property of LeafBucket
|
|
254
|
+
delete bucket.peers;
|
|
255
|
+
// @ts-expect-error left is not a property of LeafBucket
|
|
256
|
+
bucket.left = left;
|
|
257
|
+
// @ts-expect-error right is not a property of LeafBucket
|
|
258
|
+
bucket.right = right;
|
|
405
259
|
}
|
|
406
260
|
}
|
|
407
261
|
//# sourceMappingURL=k-bucket.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"k-bucket.js","sourceRoot":"","sources":["../../../src/routing-table/k-bucket.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"k-bucket.js","sourceRoot":"","sources":["../../../src/routing-table/k-bucket.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/routing-table/refresh.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/routing-table/refresh.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAU,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAOxE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,eAAe,CAAA;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,WAAW,CAAA;IACxB,YAAY,EAAE,YAAY,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAQ;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IAC5C,OAAO,CAAC,QAAQ,CAAC,6BAA6B,CAAQ;IACtD,OAAO,CAAC,gBAAgB,CAAC,CAA+B;gBAE3C,UAAU,EAAE,6BAA6B,EAAE,IAAI,EAAE,uBAAuB;IAY/E,UAAU,IAAK,OAAO,CAAC,IAAI,CAAC;IAK5B,IAAI,IAAK,OAAO,CAAC,IAAI,CAAC;IAM5B;;;;;OAKG;IACH,YAAY,CAAE,KAAK,GAAE,OAAe,GAAG,IAAI;IAyDrC,0BAA0B,CAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBhG,wCAAwC,CAAE,eAAe,EAAE,MAAM,GAAG,IAAI,EAAE;IAepE,qBAAqB,CAAE,wBAAwB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAazE,WAAW,CAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,wBAAwB,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA8BvH;;;OAGG;IACH,gBAAgB,IAAK,MAAM;IAc3B;;OAEG;IACH,eAAe,CAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAY9C;;OAEG;IACD,cAAc,IAAK,SAAS,CAAC,MAAM,CAAC;CAoBvC"}
|