1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
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 | An addressable event 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` addressable event, 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.
|