UNPKG

@libp2p/peer-store

Version:

Stores information about peers libp2p knows on the network

179 lines 6.06 kB
/** * @packageDocumentation * * The peer store is where libp2p stores data about the peers it has encountered on the network. */ import { peerIdFromCID } from '@libp2p/peer-id'; import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'; import all from 'it-all'; import { PersistentStore } from './store.js'; /** * An implementation of PeerStore that stores data in a Datastore */ class PersistentPeerStore { store; events; peerId; log; constructor(components, init = {}) { this.log = components.logger.forComponent('libp2p:peer-store'); this.events = components.events; this.peerId = components.peerId; this.store = new PersistentStore(components, init); } [Symbol.toStringTag] = '@libp2p/peer-store'; async forEach(fn, query) { this.log.trace('forEach await read lock'); const release = await this.store.lock.readLock(); this.log.trace('forEach got read lock'); try { for await (const peer of this.store.all(query)) { fn(peer); } } finally { this.log.trace('forEach release read lock'); release(); } } async all(query) { this.log.trace('all await read lock'); const release = await this.store.lock.readLock(); this.log.trace('all got read lock'); try { return await all(this.store.all(query)); } finally { this.log.trace('all release read lock'); release(); } } async delete(peerId) { this.log.trace('delete await write lock'); const release = await this.store.lock.writeLock(); this.log.trace('delete got write lock'); try { await this.store.delete(peerId); } finally { this.log.trace('delete release write lock'); release(); } } async has(peerId) { this.log.trace('has await read lock'); const release = await this.store.lock.readLock(); this.log.trace('has got read lock'); try { return await this.store.has(peerId); } finally { this.log.trace('has release read lock'); release(); } } async get(peerId) { this.log.trace('get await read lock'); const release = await this.store.lock.readLock(); this.log.trace('get got read lock'); try { return await this.store.load(peerId); } finally { this.log.trace('get release read lock'); release(); } } async save(id, data) { this.log.trace('save await write lock'); const release = await this.store.lock.writeLock(); this.log.trace('save got write lock'); try { const result = await this.store.save(id, data); this.#emitIfUpdated(id, result); return result.peer; } finally { this.log.trace('save release write lock'); release(); } } async patch(id, data) { this.log.trace('patch await write lock'); const release = await this.store.lock.writeLock(); this.log.trace('patch got write lock'); try { const result = await this.store.patch(id, data); this.#emitIfUpdated(id, result); return result.peer; } finally { this.log.trace('patch release write lock'); release(); } } async merge(id, data) { this.log.trace('merge await write lock'); const release = await this.store.lock.writeLock(); this.log.trace('merge got write lock'); try { const result = await this.store.merge(id, data); this.#emitIfUpdated(id, result); return result.peer; } finally { this.log.trace('merge release write lock'); release(); } } async consumePeerRecord(buf, expectedPeer) { const envelope = await RecordEnvelope.openAndCertify(buf, PeerRecord.DOMAIN); const peerId = peerIdFromCID(envelope.publicKey.toCID()); if (expectedPeer?.equals(peerId) === false) { this.log('envelope peer id was not the expected peer id - expected: %p received: %p', expectedPeer, peerId); return false; } const peerRecord = PeerRecord.createFromProtobuf(envelope.payload); let peer; try { peer = await this.get(peerId); } catch (err) { if (err.name !== 'NotFoundError') { throw err; } } // ensure seq is greater than, or equal to, the last received if (peer?.peerRecordEnvelope != null) { const storedEnvelope = await RecordEnvelope.createFromProtobuf(peer.peerRecordEnvelope); const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload); if (storedRecord.seqNumber >= peerRecord.seqNumber) { this.log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber); return false; } } await this.patch(peerRecord.peerId, { peerRecordEnvelope: buf, addresses: peerRecord.multiaddrs.map(multiaddr => ({ isCertified: true, multiaddr })) }); return true; } #emitIfUpdated(id, result) { if (!result.updated) { return; } if (this.peerId.equals(id)) { this.events.safeDispatchEvent('self:peer:update', { detail: result }); } else { this.events.safeDispatchEvent('peer:update', { detail: result }); } } } export function persistentPeerStore(components, init = {}) { return new PersistentPeerStore(components, init); } //# sourceMappingURL=index.js.map