-
Notifications
You must be signed in to change notification settings - Fork 602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NIP-66 Relay Discovery and Liveness Monitoring (Draft 7) #230
Open
dskvr
wants to merge
35
commits into
nostr-protocol:master
Choose a base branch
from
dskvr:nip-59-relay-status
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
4bec3aa
NIP-59 Relay status and meta
dskvr de9e410
A use case, fix text formatting
dskvr 2a2fbc3
Consistent formatting
dskvr 3bd4457
minimal -> minimum
dskvr 1a154dc
Fix typo
dskvr 2d10a62
change schema
dskvr 24ed654
asc -> desc
dskvr 3c2f2c6
add two new tags and fix some small typos
dskvr a86f7dc
add new tags to example
dskvr 649e40a
fix formatting
dskvr 31675f0
remove comma from last item in array
dskvr 7bed3f7
missing comma
dskvr 5c5f08c
update language as per discussion
dskvr 7316506
rename file
dskvr 3b50d3d
fix typo
dskvr 6c6251c
fix inconsistency in schema description
dskvr 29a8acb
improve g tag and add language for IP data usage
dskvr 94da0c1
NIP-66 Winter-2023 Update
dskvr 71bd3a0
Merge branch 'master' into nip-59-relay-status
dskvr 956f825
dec-23 update
dskvr 1bc98b5
fix as/asn tags and verbage for 1066
dskvr 9a3c5c0
add self-reporting
dskvr b8b07a2
fix event kind collision
dskvr 26ef08c
reorganize kinds to be more intuitive
dskvr 913dd3a
Fix formatting
dskvr 154ffc1
changes
dskvr 2db9908
limitations->limitation fix, integer solution, nested obj disclaimed
dskvr 41feba2
fix mismatch between schema and example
dskvr be0ebd5
Fix some typos, improve language, add example 1066 event
dskvr f83c49f
draft6
dskvr ceabecc
draft7
dskvr 42c5101
minor update to k tag that provides support for blocked kinds.
dskvr a109ea7
language update
dskvr fa73074
content SHOULD contain stringified NIP-11
dskvr cc3d7c6
Fix typos
dskvr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
# 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 | ||
{ | ||
"kind": 30166, | ||
"created_at": 1722173222, | ||
"content": "{}", | ||
"tags": [ | ||
[ "d", "wss://somerelay.abc/" ] | ||
], | ||
"pubkey": "<pubkey>", | ||
"sig": "<signature>", | ||
"id": "<eventid>" | ||
} | ||
``` | ||
|
||
This event signals that the relay at `wss://somerelay.abc/` was reported "online" by `<pubkey>` at timestamp `1722173222`. This event **MAY** be extended upon to include more information. | ||
|
||
## Kinds | ||
`NIP-66` defines two (2) event kinds, `30166` and `10166` | ||
|
||
| kind | name | description | | ||
|-------|----------------------------|-----------------------------------------------------------------------------------------| | ||
| [30166](#k30166) | Relay Discovery | A PRE that is published by a monitor when a relay is online | | ||
| [10166](#k10166) | Relay Monitor Announcement | An RE that stores data that signals the intent of a pubkey to monitor relays and publish `30166` events at a regular _frequency_ | | ||
|
||
## Ontology | ||
- `Relay Operator`: someone who operates a relay | ||
- `Monitor`: A pubkey that monitors relays and publishes `30166` events at the frequency specified in their `10166` event. | ||
- `Ad-hoc Monitor`: A pubkey that monitors relays and publishes `30166` events at an irregular frequency. | ||
- `Monitor Service`: A group or individual that monitors relays using one or more `Monitors`. | ||
- `Check`: a specific data point that is tested or aggregated by a monitor. | ||
|
||
## `30166`: "Relay Discovery" <a id="k30166"></a> | ||
|
||
### 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 | ||
Discovery of relays over nostr. | ||
|
||
### Schema | ||
|
||
#### Content | ||
`30166` content fields **SHOULD** 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/URI. The `#d` tag **must** be included in the `event.tags[]` array. Index position `1` **must** be the relay websocket URL/URI. If a URL it **SHOULD** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6). For relays not accessible via conventional means but rather by an npub/pubkey, an npub/pubkey **MAY** be used in place of a URL. | ||
```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", "42" ] | ||
``` | ||
|
||
- `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" ], //no payment required, is public | ||
[ "R", "!auth" ], //no authentication required | ||
``` | ||
|
||
- `t`: "Topics" _From NIP-11 "Informational Document" `nip11.tags[]`_ | ||
```json | ||
[ "t", "nsfw" ] | ||
``` | ||
|
||
- `k`: Accepted/Blocked Kinds [`NIP-22`] | ||
```json | ||
[ "k", "0" ], | ||
[ "k", "3" ], | ||
[ "k", "10002" ] | ||
``` | ||
|
||
or for blocked 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": "<eventid>", | ||
"pubkey": "<monitor's pubkey>", | ||
"created_at": "<created_at [some recent date ...]>", | ||
"signature": "<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 ] | ||
] | ||
} | ||
``` | ||
|
||
## `10166`: "Relay Monitor Announcement" Events <a id="k10166"></a> | ||
|
||
### 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 `30166` events. This event is optional and is intended for monitors who intend to provide monitoring services at a regular and predictable frequency. | ||
|
||
### Purpose | ||
To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities. Absence of this event implies the monitor is ad-hoc and does not publish events at a predictable frequency, and relies on mechanisms to infer data integrity, such as web-of-trust. | ||
|
||
### Schema | ||
|
||
#### Standard 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. | ||
|
||
```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. 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. Due to the rapidly evolving nature of relays, enumeration is organic and not strictly defined. But examples of some checks could be websocket `open/read/write/auth`, `nip11` checks, `dns` and `geo` checks, and and any other checks the monitor may deem useful.. 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": "<eventid>", | ||
"pubkey": "<monitor's pubkey>", | ||
"created_at": "<created_at [some recent date ...]>", | ||
"signature": "<signature>", | ||
"content": "", | ||
"tags": [ | ||
|
||
[ "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" ] | ||
] | ||
} | ||
``` | ||
|
||
## Methodology | ||
|
||
### Monitors | ||
1. A _Relay Monitor_ checks the liveness and potentially other attributes of a relay. | ||
|
||
2. _Relay Monitor_ publishes a kind `30166` note when a relay it is monitoring is online. If the monitor has a `10166` event, events should be published at the frequency defined in their `10166` note. | ||
|
||
_Any pubkey that publishes `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 statically or dynamically defined monitor's `pubkey` and a `created_at` value respective of the monitor's published `frequency`. If the monitor has no stated frequency, other mechanisms should be employed to determine data integrity. | ||
|
||
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 with respect to `frequency` value of any particular monitor. | ||
|
||
4. The reliability and trustworthiness of a _Relay Monitor_ could be established via web-of-trust, reviews or similar mechanisms. | ||
|
||
## Risk Mitigation | ||
|
||
- When a client implements `NIP-66` events, the client should have a fallback if `NIP-66` events cannot be located. | ||
|
||
- A `Monitor` or `Ad-hoc Monitor` may publish erroneous `30166` events, intentionally or otherwise. Therefor, it's important to program defensively to limit the impact of such events. This can be achieved with web-of-trust, reviews, fallbacks and/or data-aggregation for example. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are these measured?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
read:
time.begin
subscribe{ kinds: [1], limit: 1 }
, subscription fulfilled or EOSE recieved (whichever first)time.end
write:
time.begin
send event, ok (success[a,b]/fail) receivedtime.end
Notes:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some thought,
read
andwrite
should probably be removed from this NIP. For these kinds of tests to be meaningful in the present-day nostr climate requires more context.I wrote an auditor, similar to to mike's relaytester, and it seems clear that read checks will be useful, but with very specific parameters to highlight strengths and weaknesses between relays.
How to propagate or aggregate this data is still unclear, but it is very clear (and has been for a while tbh) that the simple read and write checks of yester-year provide little to no value anymore. I even completely disregard them in the new nostr.watch NIP-66 client.