@libp2p/kad-dht 0.28.6

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 (166) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +105 -0
  3. package/dist/src/constants.d.ts +20 -0
  4. package/dist/src/constants.d.ts.map +1 -0
  5. package/dist/src/constants.js +34 -0
  6. package/dist/src/constants.js.map +1 -0
  7. package/dist/src/content-fetching/index.d.ts +55 -0
  8. package/dist/src/content-fetching/index.d.ts.map +1 -0
  9. package/dist/src/content-fetching/index.js +190 -0
  10. package/dist/src/content-fetching/index.js.map +1 -0
  11. package/dist/src/content-routing/index.d.ts +42 -0
  12. package/dist/src/content-routing/index.d.ts.map +1 -0
  13. package/dist/src/content-routing/index.js +129 -0
  14. package/dist/src/content-routing/index.js.map +1 -0
  15. package/dist/src/dual-kad-dht.d.ts +65 -0
  16. package/dist/src/dual-kad-dht.d.ts.map +1 -0
  17. package/dist/src/dual-kad-dht.js +191 -0
  18. package/dist/src/dual-kad-dht.js.map +1 -0
  19. package/dist/src/index.d.ts +4 -0
  20. package/dist/src/index.d.ts.map +1 -0
  21. package/dist/src/index.js +15 -0
  22. package/dist/src/index.js.map +1 -0
  23. package/dist/src/kad-dht.d.ts +131 -0
  24. package/dist/src/kad-dht.d.ts.map +1 -0
  25. package/dist/src/kad-dht.js +268 -0
  26. package/dist/src/kad-dht.js.map +1 -0
  27. package/dist/src/message/dht.d.ts +297 -0
  28. package/dist/src/message/dht.js +921 -0
  29. package/dist/src/message/index.d.ts +32 -0
  30. package/dist/src/message/index.d.ts.map +1 -0
  31. package/dist/src/message/index.js +81 -0
  32. package/dist/src/message/index.js.map +1 -0
  33. package/dist/src/network.d.ts +60 -0
  34. package/dist/src/network.d.ts.map +1 -0
  35. package/dist/src/network.js +124 -0
  36. package/dist/src/network.js.map +1 -0
  37. package/dist/src/peer-list/index.d.ts +29 -0
  38. package/dist/src/peer-list/index.d.ts.map +1 -0
  39. package/dist/src/peer-list/index.js +44 -0
  40. package/dist/src/peer-list/index.js.map +1 -0
  41. package/dist/src/peer-list/peer-distance-list.d.ts +34 -0
  42. package/dist/src/peer-list/peer-distance-list.d.ts.map +1 -0
  43. package/dist/src/peer-list/peer-distance-list.js +64 -0
  44. package/dist/src/peer-list/peer-distance-list.js.map +1 -0
  45. package/dist/src/peer-routing/index.d.ts +71 -0
  46. package/dist/src/peer-routing/index.d.ts.map +1 -0
  47. package/dist/src/peer-routing/index.js +256 -0
  48. package/dist/src/peer-routing/index.js.map +1 -0
  49. package/dist/src/providers.d.ts +64 -0
  50. package/dist/src/providers.d.ts.map +1 -0
  51. package/dist/src/providers.js +208 -0
  52. package/dist/src/providers.js.map +1 -0
  53. package/dist/src/query/events.d.ts +46 -0
  54. package/dist/src/query/events.d.ts.map +1 -0
  55. package/dist/src/query/events.js +73 -0
  56. package/dist/src/query/events.js.map +1 -0
  57. package/dist/src/query/manager.d.ts +40 -0
  58. package/dist/src/query/manager.d.ts.map +1 -0
  59. package/dist/src/query/manager.js +140 -0
  60. package/dist/src/query/manager.js.map +1 -0
  61. package/dist/src/query/query-path.d.ts +58 -0
  62. package/dist/src/query/query-path.d.ts.map +1 -0
  63. package/dist/src/query/query-path.js +171 -0
  64. package/dist/src/query/query-path.js.map +1 -0
  65. package/dist/src/query/types.d.ts +16 -0
  66. package/dist/src/query/types.d.ts.map +1 -0
  67. package/dist/src/query/types.js +2 -0
  68. package/dist/src/query/types.js.map +1 -0
  69. package/dist/src/query-self.d.ts +31 -0
  70. package/dist/src/query-self.d.ts.map +1 -0
  71. package/dist/src/query-self.js +73 -0
  72. package/dist/src/query-self.js.map +1 -0
  73. package/dist/src/routing-table/generated-prefix-list-browser.d.ts +3 -0
  74. package/dist/src/routing-table/generated-prefix-list-browser.d.ts.map +1 -0
  75. package/dist/src/routing-table/generated-prefix-list-browser.js +1027 -0
  76. package/dist/src/routing-table/generated-prefix-list-browser.js.map +1 -0
  77. package/dist/src/routing-table/generated-prefix-list.d.ts +3 -0
  78. package/dist/src/routing-table/generated-prefix-list.d.ts.map +1 -0
  79. package/dist/src/routing-table/generated-prefix-list.js +4099 -0
  80. package/dist/src/routing-table/generated-prefix-list.js.map +1 -0
  81. package/dist/src/routing-table/index.d.ts +91 -0
  82. package/dist/src/routing-table/index.d.ts.map +1 -0
  83. package/dist/src/routing-table/index.js +183 -0
  84. package/dist/src/routing-table/index.js.map +1 -0
  85. package/dist/src/routing-table/refresh.d.ts +50 -0
  86. package/dist/src/routing-table/refresh.d.ts.map +1 -0
  87. package/dist/src/routing-table/refresh.js +204 -0
  88. package/dist/src/routing-table/refresh.js.map +1 -0
  89. package/dist/src/routing-table/types.d.ts +24 -0
  90. package/dist/src/routing-table/types.d.ts.map +1 -0
  91. package/dist/src/rpc/handlers/add-provider.d.ts +13 -0
  92. package/dist/src/rpc/handlers/add-provider.d.ts.map +1 -0
  93. package/dist/src/rpc/handlers/add-provider.js +42 -0
  94. package/dist/src/rpc/handlers/add-provider.js.map +1 -0
  95. package/dist/src/rpc/handlers/find-node.d.ts +18 -0
  96. package/dist/src/rpc/handlers/find-node.d.ts.map +1 -0
  97. package/dist/src/rpc/handlers/find-node.js +32 -0
  98. package/dist/src/rpc/handlers/find-node.js.map +1 -0
  99. package/dist/src/rpc/handlers/get-providers.d.ts +24 -0
  100. package/dist/src/rpc/handlers/get-providers.d.ts.map +1 -0
  101. package/dist/src/rpc/handlers/get-providers.js +60 -0
  102. package/dist/src/rpc/handlers/get-providers.js.map +1 -0
  103. package/dist/src/rpc/handlers/get-value.d.ts +27 -0
  104. package/dist/src/rpc/handlers/get-value.d.ts.map +1 -0
  105. package/dist/src/rpc/handlers/get-value.js +94 -0
  106. package/dist/src/rpc/handlers/get-value.js.map +1 -0
  107. package/dist/src/rpc/handlers/index.d.ts +13 -0
  108. package/dist/src/rpc/handlers/index.d.ts.map +1 -0
  109. package/dist/src/rpc/handlers/ping.d.ts +7 -0
  110. package/dist/src/rpc/handlers/ping.d.ts.map +1 -0
  111. package/dist/src/rpc/handlers/ping.js +9 -0
  112. package/dist/src/rpc/handlers/ping.js.map +1 -0
  113. package/dist/src/rpc/handlers/put-value.d.ts +18 -0
  114. package/dist/src/rpc/handlers/put-value.d.ts.map +1 -0
  115. package/dist/src/rpc/handlers/put-value.js +35 -0
  116. package/dist/src/rpc/handlers/put-value.js.map +1 -0
  117. package/dist/src/rpc/index.d.ts +38 -0
  118. package/dist/src/rpc/index.d.ts.map +1 -0
  119. package/dist/src/rpc/index.js +75 -0
  120. package/dist/src/rpc/index.js.map +1 -0
  121. package/dist/src/rpc/types.d.ts +6 -0
  122. package/dist/src/rpc/types.d.ts.map +1 -0
  123. package/dist/src/topology-listener.d.ts +33 -0
  124. package/dist/src/topology-listener.d.ts.map +1 -0
  125. package/dist/src/topology-listener.js +50 -0
  126. package/dist/src/topology-listener.js.map +1 -0
  127. package/dist/src/types.d.ts +143 -0
  128. package/dist/src/types.d.ts.map +1 -0
  129. package/dist/src/utils.d.ts +33 -0
  130. package/dist/src/utils.d.ts.map +1 -0
  131. package/dist/src/utils.js +89 -0
  132. package/dist/src/utils.js.map +1 -0
  133. package/package.json +200 -0
  134. package/src/constants.ts +50 -0
  135. package/src/content-fetching/index.ts +276 -0
  136. package/src/content-routing/index.ts +202 -0
  137. package/src/dual-kad-dht.ts +257 -0
  138. package/src/index.ts +21 -0
  139. package/src/kad-dht.ts +396 -0
  140. package/src/message/dht.d.ts +297 -0
  141. package/src/message/dht.js +921 -0
  142. package/src/message/dht.proto +75 -0
  143. package/src/message/index.ts +111 -0
  144. package/src/network.ts +185 -0
  145. package/src/peer-list/index.ts +54 -0
  146. package/src/peer-list/peer-distance-list.ts +93 -0
  147. package/src/peer-routing/index.ts +332 -0
  148. package/src/providers.ts +278 -0
  149. package/src/query/events.ts +126 -0
  150. package/src/query/manager.ts +188 -0
  151. package/src/query/query-path.ts +263 -0
  152. package/src/query/types.ts +22 -0
  153. package/src/query-self.ts +106 -0
  154. package/src/routing-table/generated-prefix-list-browser.ts +1026 -0
  155. package/src/routing-table/generated-prefix-list.ts +4098 -0
  156. package/src/routing-table/index.ts +265 -0
  157. package/src/routing-table/refresh.ts +263 -0
  158. package/src/rpc/handlers/add-provider.ts +63 -0
  159. package/src/rpc/handlers/find-node.ts +57 -0
  160. package/src/rpc/handlers/get-providers.ts +95 -0
  161. package/src/rpc/handlers/get-value.ts +130 -0
  162. package/src/rpc/handlers/ping.ts +13 -0
  163. package/src/rpc/handlers/put-value.ts +58 -0
  164. package/src/rpc/index.ts +118 -0
  165. package/src/topology-listener.ts +78 -0
  166. package/src/utils.ts +108 -0
@@ -0,0 +1,256 @@
1
+ import errcode from 'err-code';
2
+ import { verifyRecord } from '@libp2p/record/validators';
3
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
4
+ import { Message, MESSAGE_TYPE } from '../message/index.js';
5
+ import * as utils from '../utils.js';
6
+ import { queryErrorEvent, finalPeerEvent, valueEvent } from '../query/events.js';
7
+ import { PeerDistanceList } from '../peer-list/peer-distance-list.js';
8
+ import { Libp2pRecord } from '@libp2p/record';
9
+ import { base58btc } from 'multiformats/bases/base58';
10
+ import { logger } from '@libp2p/logger';
11
+ import { keys } from '@libp2p/crypto';
12
+ import { peerIdFromKeys } from '@libp2p/peer-id';
13
+ export class PeerRouting {
14
+ constructor(options) {
15
+ const { peerId, routingTable, peerStore, network, validators, queryManager, lan } = options;
16
+ this.peerId = peerId;
17
+ this.routingTable = routingTable;
18
+ this.peerStore = peerStore;
19
+ this.network = network;
20
+ this.validators = validators;
21
+ this.queryManager = queryManager;
22
+ this.log = logger(`libp2p:kad-dht:${lan ? 'lan' : 'wan'}:peer-routing`);
23
+ }
24
+ /**
25
+ * Look if we are connected to a peer with the given id.
26
+ * Returns its id and addresses, if found, otherwise `undefined`.
27
+ */
28
+ async findPeerLocal(peer) {
29
+ let peerData;
30
+ const p = await this.routingTable.find(peer);
31
+ if (p != null) {
32
+ this.log('findPeerLocal found %p in routing table', peer);
33
+ try {
34
+ peerData = await this.peerStore.get(p);
35
+ }
36
+ catch (err) {
37
+ if (err.code !== 'ERR_NOT_FOUND') {
38
+ throw err;
39
+ }
40
+ }
41
+ }
42
+ if (peerData == null) {
43
+ try {
44
+ peerData = await this.peerStore.get(peer);
45
+ }
46
+ catch (err) {
47
+ if (err.code !== 'ERR_NOT_FOUND') {
48
+ throw err;
49
+ }
50
+ }
51
+ }
52
+ if (peerData != null) {
53
+ this.log('findPeerLocal found %p in peer store', peer);
54
+ return {
55
+ id: peerData.id,
56
+ multiaddrs: peerData.addresses.map((address) => address.multiaddr),
57
+ protocols: []
58
+ };
59
+ }
60
+ }
61
+ /**
62
+ * Get a value via rpc call for the given parameters
63
+ */
64
+ async *_getValueSingle(peer, key, options = {}) {
65
+ const msg = new Message(MESSAGE_TYPE.GET_VALUE, key, 0);
66
+ yield* this.network.sendRequest(peer, msg, options);
67
+ }
68
+ /**
69
+ * Get the public key directly from a node
70
+ */
71
+ async *getPublicKeyFromNode(peer, options = {}) {
72
+ const pkKey = utils.keyForPublicKey(peer);
73
+ for await (const event of this._getValueSingle(peer, pkKey, options)) {
74
+ yield event;
75
+ if (event.name === 'PEER_RESPONSE' && event.record != null) {
76
+ const recPeer = await peerIdFromKeys(keys.marshalPublicKey({ bytes: event.record.value }));
77
+ // compare hashes of the pub key
78
+ if (!recPeer.equals(peer)) {
79
+ throw errcode(new Error('public key does not match id'), 'ERR_PUBLIC_KEY_DOES_NOT_MATCH_ID');
80
+ }
81
+ if (recPeer.publicKey == null) {
82
+ throw errcode(new Error('public key missing'), 'ERR_PUBLIC_KEY_MISSING');
83
+ }
84
+ yield valueEvent({ from: peer, value: recPeer.publicKey });
85
+ }
86
+ }
87
+ throw errcode(new Error(`Node not responding with its public key: ${peer.toString(base58btc)}`), 'ERR_INVALID_RECORD');
88
+ }
89
+ /**
90
+ * Search for a peer with the given ID
91
+ */
92
+ async *findPeer(id, options = {}) {
93
+ this.log('findPeer %p', id);
94
+ // Try to find locally
95
+ const pi = await this.findPeerLocal(id);
96
+ // already got it
97
+ if (pi != null) {
98
+ this.log('found local');
99
+ yield finalPeerEvent({
100
+ from: this.peerId,
101
+ peer: pi
102
+ });
103
+ return;
104
+ }
105
+ const key = await utils.convertPeerId(id);
106
+ const peers = this.routingTable.closestPeers(key);
107
+ // sanity check
108
+ const match = peers.find((p) => p.equals(id));
109
+ if (match != null) {
110
+ try {
111
+ const peer = await this.peerStore.get(id);
112
+ this.log('found in peerStore');
113
+ yield finalPeerEvent({
114
+ from: this.peerId,
115
+ peer: {
116
+ id: peer.id,
117
+ multiaddrs: peer.addresses.map((address) => address.multiaddr),
118
+ protocols: []
119
+ }
120
+ });
121
+ return;
122
+ }
123
+ catch (err) {
124
+ if (err.code !== 'ERR_NOT_FOUND') {
125
+ throw err;
126
+ }
127
+ }
128
+ }
129
+ const self = this; // eslint-disable-line @typescript-eslint/no-this-alias
130
+ const findPeerQuery = async function* ({ peer, signal }) {
131
+ const request = new Message(MESSAGE_TYPE.FIND_NODE, id.toBytes(), 0);
132
+ for await (const event of self.network.sendRequest(peer, request, { signal })) {
133
+ yield event;
134
+ if (event.name === 'PEER_RESPONSE') {
135
+ const match = event.closer.find((p) => p.id.equals(id));
136
+ // found the peer
137
+ if (match != null) {
138
+ yield finalPeerEvent({ from: event.from, peer: match });
139
+ }
140
+ }
141
+ }
142
+ };
143
+ let foundPeer = false;
144
+ for await (const event of this.queryManager.run(id.toBytes(), peers, findPeerQuery, options)) {
145
+ if (event.name === 'FINAL_PEER') {
146
+ foundPeer = true;
147
+ }
148
+ yield event;
149
+ }
150
+ if (!foundPeer) {
151
+ yield queryErrorEvent({ from: this.peerId, error: errcode(new Error('Not found'), 'ERR_NOT_FOUND') });
152
+ }
153
+ }
154
+ /**
155
+ * Kademlia 'node lookup' operation on a key, which could be a the
156
+ * bytes from a multihash or a peer ID
157
+ */
158
+ async *getClosestPeers(key, options = {}) {
159
+ this.log('getClosestPeers to %b', key);
160
+ const id = await utils.convertBuffer(key);
161
+ const tablePeers = this.routingTable.closestPeers(id);
162
+ const self = this; // eslint-disable-line @typescript-eslint/no-this-alias
163
+ const peers = new PeerDistanceList(id, this.routingTable.kBucketSize);
164
+ await Promise.all(tablePeers.map(async (peer) => await peers.add(peer)));
165
+ const getCloserPeersQuery = async function* ({ peer, signal }) {
166
+ self.log('closerPeersSingle %s from %p', uint8ArrayToString(key, 'base32'), peer);
167
+ const request = new Message(MESSAGE_TYPE.FIND_NODE, key, 0);
168
+ yield* self.network.sendRequest(peer, request, { signal });
169
+ };
170
+ for await (const event of this.queryManager.run(key, tablePeers, getCloserPeersQuery, options)) {
171
+ yield event;
172
+ if (event.name === 'PEER_RESPONSE') {
173
+ await Promise.all(event.closer.map(async (peerData) => await peers.add(peerData.id)));
174
+ }
175
+ }
176
+ this.log('found %d peers close to %b', peers.length, key);
177
+ for (const peer of peers.peers) {
178
+ yield finalPeerEvent({
179
+ from: this.peerId,
180
+ peer: {
181
+ id: peer,
182
+ multiaddrs: (await (this.peerStore.addressBook.get(peer)) ?? []).map(addr => addr.multiaddr),
183
+ protocols: []
184
+ }
185
+ });
186
+ }
187
+ }
188
+ /**
189
+ * Query a particular peer for the value for the given key.
190
+ * It will either return the value or a list of closer peers.
191
+ *
192
+ * Note: The peerStore is updated with new addresses found for the given peer.
193
+ */
194
+ async *getValueOrPeers(peer, key, options = {}) {
195
+ for await (const event of this._getValueSingle(peer, key, options)) {
196
+ if (event.name === 'PEER_RESPONSE') {
197
+ if (event.record != null) {
198
+ // We have a record
199
+ try {
200
+ await this._verifyRecordOnline(event.record);
201
+ }
202
+ catch (err) {
203
+ const errMsg = 'invalid record received, discarded';
204
+ this.log(errMsg);
205
+ yield queryErrorEvent({ from: event.from, error: errcode(new Error(errMsg), 'ERR_INVALID_RECORD') });
206
+ continue;
207
+ }
208
+ }
209
+ }
210
+ yield event;
211
+ }
212
+ }
213
+ /**
214
+ * Verify a record, fetching missing public keys from the network.
215
+ * Throws an error if the record is invalid.
216
+ */
217
+ async _verifyRecordOnline(record) {
218
+ await verifyRecord(this.validators, new Libp2pRecord(record.key, record.value, record.timeReceived));
219
+ }
220
+ /**
221
+ * Get the nearest peers to the given query, but if closer
222
+ * than self
223
+ */
224
+ async getCloserPeersOffline(key, closerThan) {
225
+ const id = await utils.convertBuffer(key);
226
+ const ids = this.routingTable.closestPeers(id);
227
+ const output = [];
228
+ for (const peerId of ids) {
229
+ if (peerId.equals(closerThan)) {
230
+ continue;
231
+ }
232
+ try {
233
+ const addresses = await this.peerStore.addressBook.get(peerId);
234
+ const protocols = await this.peerStore.protoBook.get(peerId);
235
+ output.push({
236
+ id: peerId,
237
+ multiaddrs: addresses.map((address) => address.multiaddr),
238
+ protocols
239
+ });
240
+ }
241
+ catch (err) {
242
+ if (err.code !== 'ERR_NOT_FOUND') {
243
+ throw err;
244
+ }
245
+ }
246
+ }
247
+ if (output.length > 0) {
248
+ this.log('getCloserPeersOffline found %d peer(s) closer to %b than %p', output.length, key, closerThan);
249
+ }
250
+ else {
251
+ this.log('getCloserPeersOffline could not find peer closer to %b than %p', key, closerThan);
252
+ }
253
+ return output;
254
+ }
255
+ }
256
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/peer-routing/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { Datastore } from 'interface-datastore';
2
+ import type { Startable } from '@libp2p/interfaces';
3
+ import type { CID } from 'multiformats';
4
+ import type { PeerId } from '@libp2p/interfaces/peer-id';
5
+ export interface ProvidersOptions {
6
+ datastore: Datastore;
7
+ cacheSize?: number;
8
+ /**
9
+ * How often invalid records are cleaned. (in seconds)
10
+ */
11
+ cleanupInterval?: number;
12
+ /**
13
+ * How long is a provider valid for. (in seconds)
14
+ */
15
+ provideValidity?: number;
16
+ }
17
+ /**
18
+ * This class manages known providers.
19
+ * A provider is a peer that we know to have the content for a given CID.
20
+ *
21
+ * Every `cleanupInterval` providers are checked if they
22
+ * are still valid, i.e. younger than the `provideValidity`.
23
+ * If they are not, they are deleted.
24
+ *
25
+ * To ensure the list survives restarts of the daemon,
26
+ * providers are stored in the datastore, but to ensure
27
+ * access is fast there is an LRU cache in front of that.
28
+ */
29
+ export declare class Providers implements Startable {
30
+ private readonly datastore;
31
+ private readonly cache;
32
+ private readonly cleanupInterval;
33
+ private readonly provideValidity;
34
+ private readonly syncQueue;
35
+ private started;
36
+ private cleaner?;
37
+ constructor(options: ProvidersOptions);
38
+ isStarted(): boolean;
39
+ /**
40
+ * Start the provider cleanup service
41
+ */
42
+ start(): Promise<void>;
43
+ /**
44
+ * Release any resources.
45
+ */
46
+ stop(): Promise<void>;
47
+ /**
48
+ * Check all providers if they are still valid, and if not delete them
49
+ */
50
+ _cleanup(): Promise<void>;
51
+ /**
52
+ * Get the currently known provider peer ids for a given CID
53
+ */
54
+ _getProvidersMap(cid: CID): Promise<Map<string, Date>>;
55
+ /**
56
+ * Add a new provider for the given CID
57
+ */
58
+ addProvider(cid: CID, provider: PeerId): Promise<void>;
59
+ /**
60
+ * Get a list of providers for the given CID
61
+ */
62
+ getProviders(cid: CID): Promise<PeerId[]>;
63
+ }
64
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/providers.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAIxD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,SAAS,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,SAAU,YAAW,SAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAW;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAQ;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAO;IACjC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAC,CAAc;gBAEjB,OAAO,EAAE,gBAAgB;IAWtC,SAAS;IAIT;;OAEG;IACG,KAAK;IAiBX;;OAEG;IACG,IAAI;IASV;;OAEG;IACG,QAAQ;IAkEd;;OAEG;IACG,gBAAgB,CAAE,GAAG,EAAE,GAAG;IAYhC;;OAEG;IACG,WAAW,CAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM;IAgB7C;;OAEG;IACG,YAAY,CAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAUjD"}
@@ -0,0 +1,208 @@
1
+ import cache from 'hashlru';
2
+ import varint from 'varint';
3
+ import { Key } from 'interface-datastore/key';
4
+ import Queue from 'p-queue';
5
+ import { PROVIDERS_CLEANUP_INTERVAL, PROVIDERS_VALIDITY, PROVIDERS_LRU_CACHE_SIZE, PROVIDER_KEY_PREFIX } from './constants.js';
6
+ import { logger } from '@libp2p/logger';
7
+ import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
8
+ import { peerIdFromString } from '@libp2p/peer-id';
9
+ const log = logger('libp2p:kad-dht:providers');
10
+ /**
11
+ * This class manages known providers.
12
+ * A provider is a peer that we know to have the content for a given CID.
13
+ *
14
+ * Every `cleanupInterval` providers are checked if they
15
+ * are still valid, i.e. younger than the `provideValidity`.
16
+ * If they are not, they are deleted.
17
+ *
18
+ * To ensure the list survives restarts of the daemon,
19
+ * providers are stored in the datastore, but to ensure
20
+ * access is fast there is an LRU cache in front of that.
21
+ */
22
+ export class Providers {
23
+ constructor(options) {
24
+ const { datastore, cacheSize, cleanupInterval, provideValidity } = options;
25
+ this.datastore = datastore;
26
+ this.cleanupInterval = cleanupInterval ?? PROVIDERS_CLEANUP_INTERVAL;
27
+ this.provideValidity = provideValidity ?? PROVIDERS_VALIDITY;
28
+ this.cache = cache(cacheSize ?? PROVIDERS_LRU_CACHE_SIZE);
29
+ this.syncQueue = new Queue({ concurrency: 1 });
30
+ this.started = false;
31
+ }
32
+ isStarted() {
33
+ return this.started;
34
+ }
35
+ /**
36
+ * Start the provider cleanup service
37
+ */
38
+ async start() {
39
+ if (this.started) {
40
+ return;
41
+ }
42
+ this.started = true;
43
+ this.cleaner = setInterval(() => {
44
+ this._cleanup().catch(err => {
45
+ log.error(err);
46
+ });
47
+ }, this.cleanupInterval);
48
+ }
49
+ /**
50
+ * Release any resources.
51
+ */
52
+ async stop() {
53
+ this.started = false;
54
+ if (this.cleaner != null) {
55
+ clearInterval(this.cleaner);
56
+ this.cleaner = undefined;
57
+ }
58
+ }
59
+ /**
60
+ * Check all providers if they are still valid, and if not delete them
61
+ */
62
+ async _cleanup() {
63
+ return await this.syncQueue.add(async () => {
64
+ const start = Date.now();
65
+ let count = 0;
66
+ let deleteCount = 0;
67
+ const deleted = new Map();
68
+ const batch = this.datastore.batch();
69
+ // Get all provider entries from the datastore
70
+ const query = this.datastore.query({ prefix: PROVIDER_KEY_PREFIX });
71
+ for await (const entry of query) {
72
+ try {
73
+ // Add a delete to the batch for each expired entry
74
+ const { cid, peerId } = parseProviderKey(entry.key);
75
+ const time = readTime(entry.value).getTime();
76
+ const now = Date.now();
77
+ const delta = now - time;
78
+ const expired = delta > this.provideValidity;
79
+ log('comparing: %d - %d = %d > %d %s', now, time, delta, this.provideValidity, expired ? '(expired)' : '');
80
+ if (expired) {
81
+ deleteCount++;
82
+ batch.delete(entry.key);
83
+ const peers = deleted.get(cid) ?? new Set();
84
+ peers.add(peerId);
85
+ deleted.set(cid, peers);
86
+ }
87
+ count++;
88
+ }
89
+ catch (err) {
90
+ log.error(err.message);
91
+ }
92
+ }
93
+ // Commit the deletes to the datastore
94
+ if (deleted.size > 0) {
95
+ log('deleting %d / %d entries', deleteCount, count);
96
+ await batch.commit();
97
+ }
98
+ else {
99
+ log('nothing to delete');
100
+ }
101
+ // Clear expired entries from the cache
102
+ for (const [cid, peers] of deleted) {
103
+ const key = makeProviderKey(cid);
104
+ const provs = this.cache.get(key);
105
+ if (provs != null) {
106
+ for (const peerId of peers) {
107
+ provs.delete(peerId);
108
+ }
109
+ if (provs.size === 0) {
110
+ this.cache.remove(key);
111
+ }
112
+ else {
113
+ this.cache.set(key, provs);
114
+ }
115
+ }
116
+ }
117
+ log('Cleanup successful (%dms)', Date.now() - start);
118
+ });
119
+ }
120
+ /**
121
+ * Get the currently known provider peer ids for a given CID
122
+ */
123
+ async _getProvidersMap(cid) {
124
+ const cacheKey = makeProviderKey(cid);
125
+ let provs = this.cache.get(cacheKey);
126
+ if (provs == null) {
127
+ provs = await loadProviders(this.datastore, cid);
128
+ this.cache.set(cacheKey, provs);
129
+ }
130
+ return provs;
131
+ }
132
+ /**
133
+ * Add a new provider for the given CID
134
+ */
135
+ async addProvider(cid, provider) {
136
+ return await this.syncQueue.add(async () => {
137
+ log('%p provides %s', provider, cid);
138
+ const provs = await this._getProvidersMap(cid);
139
+ log('loaded %s provs', provs.size);
140
+ const now = new Date();
141
+ provs.set(provider.toString(), now);
142
+ const dsKey = makeProviderKey(cid);
143
+ this.cache.set(dsKey, provs);
144
+ await writeProviderEntry(this.datastore, cid, provider, now);
145
+ });
146
+ }
147
+ /**
148
+ * Get a list of providers for the given CID
149
+ */
150
+ async getProviders(cid) {
151
+ return await this.syncQueue.add(async () => {
152
+ log('get providers for %s', cid);
153
+ const provs = await this._getProvidersMap(cid);
154
+ return [...provs.keys()].map(peerIdStr => {
155
+ return peerIdFromString(peerIdStr);
156
+ });
157
+ });
158
+ }
159
+ }
160
+ /**
161
+ * Encode the given key its matching datastore key
162
+ */
163
+ function makeProviderKey(cid) {
164
+ const cidStr = typeof cid === 'string' ? cid : uint8ArrayToString(cid.multihash.bytes, 'base32');
165
+ return `${PROVIDER_KEY_PREFIX}/${cidStr}`;
166
+ }
167
+ /**
168
+ * Write a provider into the given store
169
+ */
170
+ async function writeProviderEntry(store, cid, peer, time) {
171
+ const dsKey = [
172
+ makeProviderKey(cid),
173
+ '/',
174
+ peer.toString()
175
+ ].join('');
176
+ const key = new Key(dsKey);
177
+ const buffer = Uint8Array.from(varint.encode(time.getTime()));
178
+ return await store.put(key, buffer);
179
+ }
180
+ /**
181
+ * Parse the CID and provider peer id from the key
182
+ */
183
+ function parseProviderKey(key) {
184
+ const parts = key.toString().split('/');
185
+ if (parts.length !== 5) {
186
+ throw new Error(`incorrectly formatted provider entry key in datastore: ${key.toString()}`);
187
+ }
188
+ return {
189
+ cid: parts[3],
190
+ peerId: parts[4]
191
+ };
192
+ }
193
+ /**
194
+ * Load providers for the given CID from the store
195
+ */
196
+ async function loadProviders(store, cid) {
197
+ const providers = new Map();
198
+ const query = store.query({ prefix: makeProviderKey(cid) });
199
+ for await (const entry of query) {
200
+ const { peerId } = parseProviderKey(entry.key);
201
+ providers.set(peerId, readTime(entry.value));
202
+ }
203
+ return providers;
204
+ }
205
+ function readTime(buf) {
206
+ return new Date(varint.decode(buf));
207
+ }
208
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/providers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { SendingQueryEvent, PeerResponseEvent, MessageType, DialingPeerEvent, AddingPeerEvent, ValueEvent, ProviderEvent, QueryErrorEvent, FinalPeerEvent } from '@libp2p/interfaces/dht';
2
+ import type { PeerData } from '@libp2p/interfaces/peer-data';
3
+ import type { PeerId } from '@libp2p/interfaces/peer-id';
4
+ import type { Libp2pRecord } from '@libp2p/record';
5
+ export interface QueryEventFields {
6
+ to: PeerId;
7
+ type: MessageType;
8
+ }
9
+ export declare function sendingQueryEvent(fields: QueryEventFields): SendingQueryEvent;
10
+ export interface PeerResponseEventField {
11
+ from: PeerId;
12
+ messageType: MessageType;
13
+ closer?: PeerData[];
14
+ providers?: PeerData[];
15
+ record?: Libp2pRecord;
16
+ }
17
+ export declare function peerResponseEvent(fields: PeerResponseEventField): PeerResponseEvent;
18
+ export interface FinalPeerEventFields {
19
+ from: PeerId;
20
+ peer: PeerData;
21
+ }
22
+ export declare function finalPeerEvent(fields: FinalPeerEventFields): FinalPeerEvent;
23
+ export interface ErrorEventFields {
24
+ from: PeerId;
25
+ error: Error;
26
+ }
27
+ export declare function queryErrorEvent(fields: ErrorEventFields): QueryErrorEvent;
28
+ export interface ProviderEventFields {
29
+ from: PeerId;
30
+ providers: PeerData[];
31
+ }
32
+ export declare function providerEvent(fields: ProviderEventFields): ProviderEvent;
33
+ export interface ValueEventFields {
34
+ from: PeerId;
35
+ value: Uint8Array;
36
+ }
37
+ export declare function valueEvent(fields: ValueEventFields): ValueEvent;
38
+ export interface PeerEventFields {
39
+ peer: PeerId;
40
+ }
41
+ export declare function addingPeerEvent(fields: PeerEventFields): AddingPeerEvent;
42
+ export interface DialingPeerEventFields {
43
+ peer: PeerId;
44
+ }
45
+ export declare function dialingPeerEvent(fields: DialingPeerEventFields): DialingPeerEvent;
46
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/query/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC9L,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAWlD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,WAAW,CAAA;CAClB;AAED,wBAAgB,iBAAiB,CAAE,MAAM,EAAE,gBAAgB,GAAG,iBAAiB,CAS9E;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,WAAW,CAAA;IACxB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAA;IACnB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAA;IACtB,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB;AAED,wBAAgB,iBAAiB,CAAE,MAAM,EAAE,sBAAsB,GAAG,iBAAiB,CAUpF;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,QAAQ,CAAA;CACf;AAED,wBAAgB,cAAc,CAAE,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAM5E;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,KAAK,CAAA;CACb;AAED,wBAAgB,eAAe,CAAE,MAAM,EAAE,gBAAgB,GAAG,eAAe,CAM1E;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,QAAQ,EAAE,CAAA;CACtB;AAED,wBAAgB,aAAa,CAAE,MAAM,EAAE,mBAAmB,GAAG,aAAa,CAMzE;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,CAAA;CAClB;AAED,wBAAgB,UAAU,CAAE,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAMhE;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,eAAe,CAAE,MAAM,EAAE,eAAe,GAAG,eAAe,CAMzE;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,gBAAgB,CAAE,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,CAMlF"}