diff --git a/packages/interface-peer-store/package.json b/packages/interface-peer-store/package.json index e3b3a4ab0..da49a10b5 100644 --- a/packages/interface-peer-store/package.json +++ b/packages/interface-peer-store/package.json @@ -154,7 +154,6 @@ "dependencies": { "@libp2p/interface-peer-id": "^2.0.0", "@libp2p/interface-peer-info": "^1.0.0", - "@libp2p/interface-record": "^2.0.0", "@libp2p/interfaces": "^3.0.0", "@multiformats/multiaddr": "^12.0.0" }, diff --git a/packages/interface-peer-store/src/index.ts b/packages/interface-peer-store/src/index.ts index b341e4bcb..e05a827f1 100644 --- a/packages/interface-peer-store/src/index.ts +++ b/packages/interface-peer-store/src/index.ts @@ -1,9 +1,9 @@ import type { PeerId } from '@libp2p/interface-peer-id' import type { Multiaddr } from '@multiformats/multiaddr' -import type { EventEmitter } from '@libp2p/interfaces/events' -import type { Envelope } from '@libp2p/interface-record' -import type { PeerInfo } from '@libp2p/interface-peer-info' +/** + * A multiaddr with an optional flag that indicates if its trustworthy + */ export interface Address { /** * Peer multiaddr @@ -16,6 +16,9 @@ export interface Address { isCertified: boolean } +/** + * Data stored in the peer store about peers + */ export interface Peer { /** * Peer's peer-id instance @@ -23,7 +26,8 @@ export interface Peer { id: PeerId /** - * Peer's addresses containing its multiaddrs and metadata + * Peer's addresses containing a list of multiaddrs and a isCertified field + * indicating if the address was loaded from a signed peer record or not */ addresses: Address[] @@ -38,9 +42,9 @@ export interface Peer { metadata: Map /** - * May be set if the key that this Peer has is an RSA key + * Tags a peer has */ - pubKey?: Uint8Array + tags: Map /** * The last peer record envelope received @@ -48,356 +52,53 @@ export interface Peer { peerRecordEnvelope?: Uint8Array } -export interface CertifiedRecord { - raw: Uint8Array - seqNumber: number -} - -export interface AddressBookEntry { - addresses: Address[] - record: CertifiedRecord -} - -export interface Book { - /** - * Get the known data of a peer - */ - get: (peerId: PeerId) => Promise - - /** - * Set the known data of a peer - */ - set: (peerId: PeerId, data: Type) => Promise - - /** - * Remove the known data of a peer - */ - delete: (peerId: PeerId) => Promise -} - -/** - * AddressBook containing a map of peerIdStr to Address. - */ -export interface AddressBook { - /** - * ConsumePeerRecord adds addresses from a signed peer record contained in a record envelope. - * This will return a boolean that indicates if the record was successfully processed and added - * into the AddressBook - */ - consumePeerRecord: (envelope: Envelope) => Promise - - /** - * Get the raw Envelope for a peer. Returns - * undefined if no Envelope is found - */ - getRawEnvelope: (peerId: PeerId) => Promise - - /** - * Get an Envelope containing a PeerRecord for the given peer. - * Returns undefined if no record exists. - */ - getPeerRecord: (peerId: PeerId) => Promise - - /** - * Add known addresses of a provided peer. - * If the peer is not known, it is set with the given addresses. - * - * @example - * - * ```js - * peerStore.addressBook.add(peerId, multiaddr) - * ``` - */ - add: (peerId: PeerId, multiaddrs: Multiaddr[]) => Promise - - /** - * Set known `multiaddrs` of a given peer. This will replace previously stored multiaddrs, if available. - * - * Replacing stored multiaddrs might result in losing obtained certified addresses, which is not desirable. - * - * Consider using `addressBook.add()` if you're not sure this is what you want to do. - * - * @example - * - * ```js - * peerStore.addressBook.add(peerId, multiaddr) - * ``` - */ - set: (peerId: PeerId, data: Multiaddr[]) => Promise - - /** - * Return the known addresses of a peer - * - * ```js - * peerStore.addressBook.get(peerId) - * // [] - * peerStore.addressBook.set(peerId, multiaddr) - * peerStore.addressBook.get(peerId) - * // [ - * // { - * // multiaddr: /ip4/140.10.2.1/tcp/8000, - * // ... - * // }, - * // { - * // multiaddr: /ip4/140.10.2.1/ws/8001 - * // ... - * // }, - * // ] - * ``` - */ - get: (peerId: PeerId) => Promise - - /** - * Remove stored addresses of a peer - * - * @example - * - * ```js - * peerStore.addressBook.delete(peerId) - * // false - * peerStore.addressBook.set(peerId, multiaddr) - * peerStore.addressBook.delete(peerId) - * // true - * ``` - */ - delete: (peerId: PeerId) => Promise -} - /** - * KeyBook containing a map of peerIdStr to their PeerId with public keys. + * Peer data used to update the peer store */ -export interface KeyBook { +export interface PeerData { /** - * Get the known `PublicKey` of a peer as a `Uint8Array` + * Peer's addresses containing its multiaddrs and metadata - multiaddrs + * passed here can be treated as certified if the `isCertifed` value is + * set to true. * - * @example - * - * ```js - * peerStore.keyBook.get(peerId) - * // undefined - * peerStore.keyBook.set(peerId, publicKey) - * peerStore.keyBook.get(peerId) - * // Uint8Array - * ``` + * If both addresses and multiaddrs are specified they will be merged + * together with entries in addresses taking precedence. */ - get: (peerId: PeerId) => Promise + addresses?: Address[] /** - * Set the known data of a peer - * - * @example + * Peer's multiaddrs - any multiaddrs passed here will be treated as + * uncertified. * - * ```js - * const publicKey = peerId.pubKey - * peerStore.keyBook.set(peerId, publicKey) - * ``` + * If both addresses and multiaddrs are specified they will be merged + * together with entries in addresses taking precedence. */ - set: (peerId: PeerId, data: Uint8Array) => Promise + multiaddrs?: Multiaddr[] /** - * Remove the known data of a peer - * - * @example - * - * ```js - * peerStore.keyBook.get(peerId) - * // undefined - * peerStore.keyBook.set(peerId, publicKey) - * peerStore.keyBook.get(peerId) - * // Uint8Array - * peerStore.keyBook.delete(peerId) - * peerStore.keyBook.get(peerId) - * // undefined - * ``` - */ - delete: (peerId: PeerId) => Promise -} - -/** - * MetadataBook containing a map of peerIdStr to their metadata Map. - */ -export interface MetadataBook extends Book> { - /** - * Set a specific metadata value - * - * @example - * - * ```js - * peerStore.metadataBook.setValue(peerId, 'nickname', uint8ArrayFromString('homePeer')) - * peerStore.metadataBook.getValue(peerId, 'nickname') - * // Uint8Array - * ``` - */ - setValue: (peerId: PeerId, key: string, value: Uint8Array) => Promise - - /** - * Get specific metadata value, if it exists - * - * @example - * - * ```js - * peerStore.metadataBook.getValue(peerId, 'location') - * // undefined - * peerStore.metadataBook.setValue(peerId, 'location', uint8ArrayFromString('Berlin')) - * peerStore.metadataBook.getValue(peerId, 'location') - * // Uint8Array - * ``` + * Peer's supported protocols */ - getValue: (peerId: PeerId, key: string) => Promise + protocols?: string[] /** - * Deletes the provided peer metadata key from the book - * - * @example - * - * ```js - * peerStore.metadataBook.getValue(peerId, 'location') - * // undefined - * peerStore.metadataBook.setValue(peerId, 'location', uint8ArrayFromString('Berlin')) - * peerStore.metadataBook.getValue(peerId, 'location') - * // Uint8Array - * ``` + * Peer's metadata map */ - deleteValue: (peerId: PeerId, key: string) => Promise -} + metadata?: Map | Record -/** - * ProtoBook containing a map of peerIdStr to supported protocols. - */ -export interface ProtoBook extends Book { /** - * Adds known protocols of a provided peer. - * If the peer was not known before, it will be added. - * - * @example - * - * ```js - * peerStore.protoBook.add(peerId, [ '/proto/1.0.0', '/proto/1.1.0' ]) - * ``` + * Peer tags */ - add: (peerId: PeerId, protocols: string[]) => Promise + tags?: Map | Record /** - * Removes known protocols of a provided peer. - * If the protocols did not exist before, nothing will be done. - * - * @example - * - * ```js - * peerStore.protoBook.remove(peerId, protocols) - * ``` + * If this Peer has an RSA key, it's public key can be set with this property */ - remove: (peerId: PeerId, protocols: string[]) => Promise -} - -export interface PeerProtocolsChangeData { - peerId: PeerId - protocols: string[] - oldProtocols: string[] -} - -export interface PeerMultiaddrsChangeData { - peerId: PeerId - multiaddrs: Multiaddr[] - oldMultiaddrs: Multiaddr[] -} - -export interface PeerPublicKeyChangeData { - peerId: PeerId publicKey?: Uint8Array - oldPublicKey?: Uint8Array -} - -export interface PeerMetadataChangeData { - peerId: PeerId - metadata: Map - oldMetadata: Map -} - -export type EventName = 'peer' | 'change:protocols' | 'change:multiaddrs' | 'change:pubkey' | 'change:metadata' - -export interface PeerStoreEvents { - /** - * This event is emitted when a new peer is added to the peerStore - * - * @example - * - * ```js - * peerStore.addEventListener('peer', (event) => { - * const peerInfo = event.detail - * // ... - * }) - * ``` - */ - 'peer': CustomEvent - - /** - * This event is emitted when known protocols for a peer change - * - * @example - * - * ```js - * peerStore.addEventListener('change:protocols', (event) => { - * const { peerId, protocols, oldProtocols } = event.detail - * // ... - * }) - * ``` - */ - 'change:protocols': CustomEvent /** - * This event is emitted when known multiaddrs for a peer change - * - * @example - * - * ```js - * peerStore.addEventListener('change:multiaddrs', (event) => { - * const { peerId, multiaddrs, oldMultiaddrs } = event.detail - * // ... - * }) - * ``` - */ - 'change:multiaddrs': CustomEvent - - /** - * This event is emitted when the public key for a peer changes - * - * @example - * - * ```js - * peerStore.addEventListener('change:pubkey', (event) => { - * const { peerId, publicKey, oldPublicKey } = event.detail - * // ... - * }) - * ``` - */ - 'change:pubkey': CustomEvent - - /** - * This event is emitted when known metadata for a peer changes - * - * @example - * - * ```js - * peerStore.addEventListener('change:metadata', (event) => { - * const { peerId, metadata, oldMetadata } = event.detail - * // ... - * }) - * ``` + * The last peer record envelope received */ - 'change:metadata': CustomEvent -} - -export interface AddressFilter { - (peerId: PeerId, multiaddr: Multiaddr): Promise -} - -export interface AddressSorter { - (a: Address, b: Address): -1 | 0 | 1 -} - -export interface PeerStoreInit { - addressFilter?: AddressFilter + peerRecordEnvelope?: Uint8Array } export interface TagOptions { @@ -413,23 +114,13 @@ export interface TagOptions { } export interface Tag { - /** - * The tag name - */ - name: string - /** * The tag value */ value: number } -export interface PeerStore extends EventEmitter { - addressBook: AddressBook - keyBook: KeyBook - metadataBook: MetadataBook - protoBook: ProtoBook - +export interface PeerStore { /** * Loop over every peer - the looping is async because we read from a * datastore but the peer operation is sync, this is to prevent @@ -506,51 +197,41 @@ export interface PeerStore extends EventEmitter { get: (peerId: PeerId) => Promise /** - * Call this method to add a tag to a peer. Used by the connection manager - * to reconnect to peers, choose peers to disconnect from, etc. + * Adds a peer to the peer store, overwriting any existing data * * @example * - * Values are between 0-100 - * * ```js - * peerStore.tagPeer(peerId, 'my-tag', { - * value: 50 - * }) - * ``` - * - * @example - * - * Tags can be given a TTL, for example this tag will expire after 5s: - * - * * ```js - * await peerStore.tagPeer(peerId, 'my-tag', { - * value: 50, - * ttl: 5000 + * await peerStore.set(peerId, { + * multiaddrs * }) * ``` */ - tagPeer: (peerId: PeerId, tag: string, options?: TagOptions) => Promise + save: (id: PeerId, data: PeerData) => Promise /** - * This method will remove a tag from a peer + * Adds a peer to the peer store, overwriting only the passed fields * * @example * * ```js - * await peerStore.unTagPeer(peerId, 'my-tag) + * await peerStore.patch(peerId, { + * multiaddrs + * }) * ``` */ - unTagPeer: (peerId: PeerId, tag: string) => Promise + patch: (id: PeerId, data: PeerData) => Promise /** - * Return all tags that have been set on the passed peer + * Adds a peer to the peer store, deeply merging any existing data. * * @example * * ```js - * const tags = await peerStore.getTags(peerId) - * // [] + * await peerStore.merge(peerId, { + * multiaddrs + * }) + * ``` */ - getTags: (peerId: PeerId) => Promise + merge: (id: PeerId, data: PeerData) => Promise }