# NIP-66: Relay Discovery and Liveness Monitoring `draft` `optional` You want to find relays. You may want to discover relays based on criteria that's up to date. You may even want to ensure that you have a complete dataset. You probably want to filter relays based on their reported liveness. In its purest form: ```json { "sig": "", "pubkey": "", "id": "", "content": "{}", "created_at": 1722173222, "kind": 30166, "tags": [ [ "d", "wss://eostagram.com/" ] ] } ``` This event signals that the relay at `wss://eostagram.com/` was reported "online" by `` at timestamp `1722173222`. This event **MAY** be extended upon to include more information. ## Kinds This NIP defines two (2) event kinds, `10166` and `30166` | kind | name | description | |-------|----------------------------|-----------------------------------------------------------------------------------------| | [10166](#k10166) | Relay Monitor Announcement | An RE that stores data to publish intent to monitor and details around their activities | | [30166](#k30166) | Relay Discovery | A PRE that is published by a monitor when a relay is online | ## Ontology - `Relay Operator`: someone who operates a relay - `Monitor Service`: a group or individual that monitors the network - `Monitor`: a piece of software that aggregates network data and publishes that data at a specified frequency. - `Check`: a specific data point that is tested or aggregated by a monitor. ## `10166`: "Relay Monitor Announcement" Events ### Summary `10166` is a replacable event herein referred to as "Relay Monitor Announcement" events. These events contain information about a publisher's intent to monitor and publish data as `NIP-66` events. ### Purpose To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities. Absence of the `10166` event is not encouraged, but if absent implies the monitor is ad-hoc and does not publish events at a predictable frequency. ### Schema #### Non-Indexed Tags - `frequency` The frequency **in seconds** at which the monitor publishes events. A string-integer at index `1` represents the expected frequency the monitor will publish `30166` events. There should only be `1` frequency per monitor. A `-1` frequency means that the monitor does not publish events at a predictable frequency. ```json [ "frequency", "3600" ] ``` - `timeout` (optional) The timeout values for various checks conducted by a monitor. Index `1` is the monitor's timeout in milliseconds. Index `2` describes what test the timeout is used for, for example `open`, `read`, `write`, `nip11`, etc. If no index `2` is provided, it is inferred that the timeout provided applies to all tests. These values can assist relay operators in understanding data signaled by the monitor in _Relay Discovery Events_. ```json [ "timeout", "2000", "open" ], [ "timeout", "2000", "read" ], [ "timeout", "3000", "write" ], [ "timeout", "2000", "nip11" ], [ "timeout", "4000", "ssl" ] ``` #### Indexed Tags - `c` "Checks" **SHOULD** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `ws`, `nip11`, `ssl`, `dns`, `geo`, etc. Other checks **MAY** be included. New types of checks **SHOULD** be added to this NIP as they are needed. ```json [ "c", "ws" ], [ "c", "nip11" ], [ "c", "dns" ], [ "c", "geo" ], [ "c", "ssl" ], ``` - `g`: `NIP-52` `g` tags (geohash) ```json [ "g", "9r1652whz" ] ``` - Any other globally defined indexable tags **MAY** be included as found necessary. ### Other Requirements Monitors **SHOULD** have the following - A published `0` (NIP-1) event - A published `10002` (NIP-65) event that defines the relays the monitor publishes to. ### Robust Example of a `10166` Event ```json { "id": "", "pubkey": "", "created_at": "", "signature": "", "content": "", "tags": [ [ "url", "https://a.good.monitor/"], [ "timeout", "open", "5000" ], [ "timeout", "read", "3000" ], [ "timeout", "write", "3000" ], [ "timeout", "nip11", "3000" ], [ "frequency", "3600" ], [ "c", "ws" ], [ "c", "nip11" ], [ "c", "ssl" ], [ "c", "dns" ], [ "c", "geo" ] [ "g", "ww8p1r4t8" ] ] } ``` ## `30166`: "Relay Discovery" ### Summary `30166` is a `NIP-33` Parameterized-Replaceable Event [PRE], referred to as a "Relay Discovery" event. These events are optimized with a small footprint for protocol-level relay Discovery. ### Purpose Enables the discovery of relays via nostr protocol. ### Schema #### Content `30166` content fields **MAY** include the stringified JSON of the relay's NIP-11 informational document. This data **MAY** be provided for informational purposes only. #### `created_at` The `created_at` field in a NIP-66 event should reflect the time when the relay liveness (and potentially other data points) was checked. #### `tags` ##### Meta Tags (unindexed) - `rtt-open` The relay's open **round-trip time** in milliseconds. - `rtt-read` The relay's read **round-trip time** in milliseconds. - `rtt-write` The relay's write **round-trip time** in milliseconds. _Other `rtt` values **MAY** be present. This NIP should be updated if there is value found in more `rtt` values._ ##### Single Letter Tags (indexed) - `d` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. Index position `1` **must** be the relay websocket URL. The URL **SHOULD** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) ```json [ "d", "wss://somerelay.abc/"] ``` - `n`: Network ```json [ "n", "clearnet" ] ``` - `T`: Relay Type. Enumerated [relay type](https://github.com/nostr-protocol/nips/issues/1282) formatted as `PascalCase` ```json ["T", "PrivateInbox" ] ``` - `N`: Supported Nips _From NIP-11 "Informational Document" `nip11.supported_nips[]`_ ```json [ "N", "33" ] ``` - `R`: Requirements _NIP-11 "Informational Document" `nip11.limitations.payment_required`, `nip11.limitations.auth_required` and/or any other boolean value within `nip11.limitations[]` that is added in the future_ ```json [ "R", "payment" ], [ "R", "auth" ], ``` Since the nostr protocol does not currently support filtering on whether an indexed tag **is** or **is not** set, to make "public" and "no auth" relays discoverable requires a `!` flag ```json [ "R", "!payment" ], //is public [ "R", "!auth" ], //no authentication required ``` - `t`: "Topics" _From NIP-11 "Informational Document" `nip11.tags[]`_ ```json [ "t", "nsfw" ] ``` - `k`: Accepted Kinds ```json [ "k", "0" ], [ "k", "3" ], [ "k", "10002" ] ``` - `g`: `NIP-52` `g` tags (geohash) ```json [ "g", "9r1652whz" ] ``` - `30166` **MAY** be extended with global tags defined by other NIPs that do no collide with locally defined indices, including but not limited to: `p`, `t`, `e`, `a`, `i` and `l/L`. #### Robust Example of a `30166` Event _Relay was online, and you can filter on a number of different tags_ ```json { "id": "", "pubkey": "", "created_at": "", "signature": "", "content": "{}", "kind": 30166, "tags": [ ["d","wss://some.relay/"], ["n", "clearnet"], ["N", "40"], ["N", "33"], ["R", "!payment"], ["R", "auth"], ["g", "ww8p1r4t8"], ["p", "somehexkey..."], ["l", "en", "ISO-639-1"], ["t", "nsfw" ], ["rtt-open", 234 ] ] } ``` #### Methodology ##### Monitors 1. A _Relay Monitor_ checks the liveness of a relay at the `frequency` defined in their `10166`. 2. _Relay Monitor_ publishes a kind `30166` note when a relay it is monitoring is online. _Relay Monitors that publish `30166` events **SHOULD** at a minimum be checking that the relay is available by websocket and behaves like a relay_ ##### Clients 1. In most cases, a client **SHOULD** filter on `30166` events using either a staticly or dynamically chosen monitor's `pubkey` and a `created_at` value respective of the monitor's published `frequency`. 2. _Relay Liveness_ is subjectively determined by the client, starting with the `frequency` value of a monitor. 3. The liveness of a _Relay Monitor_ can be subjectively determined by detecting whether the _Relay Monitor_ has published events within the specified `frequency`. 4. The reliability and trustworthiness of a _Relay Monitor_ could be established via web-of-trust, reviews or similar mechanisms. ## Use Cases 1. **Geographic Relay Discovery**: Identify relays situated near a specific geographic location or within a particular country, facilitating localized network interactions. 2. **NIP Support Filtering**: Search for relays based on their support for specific Nostr Implementation Possibilities (NIPs), ensuring compatibility with desired protocol features. 3. **Accessibility Search**: Locate relays that are free to use 4. **Real-Time Status Monitoring**: Utilize a status client to display up-to-date statuses of various relays, providing insights into their current operational state. 5. **Relay Network Analysis**: Analyze connections and patterns between relays using their IP addresses, aiding in network topology understanding and security assessments. 6. **Error Detection in Relay Listings**: Spot and rectify erroneous entries in relay lists. 7. **Performance Benchmarking**: Compare relays based on performance metrics like round-trip times and uptime, aiding in the selection of the most efficient relays for specific needs. 8. **Language and Content Filtering**: Identify relays catering to specific languages or content types, enabling users to engage in a more targeted and relevant social networking experience. ## History - _**draft1** implemented in `January 2023` and proposed `February 2023`. "Too many one-letter indexable tags"_ - _**draft2** experimented with `March 2023` "Everything should be expirable"_ - _**draft3** experimented, never proposed_ - _**draft4** experimented, never proposed_ - _**draft5** proposed `December 2023`, "Needs to be indexed"_ - _**draft6** proposed `February 2024`, "Just use one-letter indexable tags" (lol) and split Discovery and parse cases._ - _**draft7** proposed `July 2024`, remove Relay Meta, offload case onto existing nips._