From 4bec3aa1efbac1ba8c353043d527fb590d99372c Mon Sep 17 00:00:00 2001 From: Sandwich <299465+dskvr@users.noreply.github.com> Date: Tue, 7 Feb 2023 14:18:15 +0100 Subject: [PATCH 01/34] NIP-59 Relay status and meta Simplify language in personas Fix error in schema example Fix Iv6 --- 59.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 59.md diff --git a/59.md b/59.md new file mode 100644 index 00000000..25942cc3 --- /dev/null +++ b/59.md @@ -0,0 +1,100 @@ +# NIP-59: Relay Status + +`draft` `optional` `author:dskvr` + +This NIP defines `30303`, a parameterized replaceable event [NIP-33], referred to as Relay Statuses. Relay Statuses use tags extensively and **may** have `.content` populated with Stringified JSON. + +## Purpose +To store relay meta-data and the result of subjective checks as queryable [NIP-12] events on nostr. + +## Personas +- **Publishers** generate and push `30303` events. Events **should** be published at a regular interval. Events **may** be stale. +- **Consumers** aggregate `30303` for insight on relays. Some example consumers are a social client or relay status client. + +## schema + +### `event.created_at` +`created_at` **should** be interpreted by consumers as `updated_at` + +### `event.tags` +Relay status events have **two** (1) required tags and **eight** (8) optional tags. + +The tags should be used to represent the Relay's abilities and meta at a point in time. Below the `tags schema` is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. + +1. `"d" == tagId[0]` The relay URL (`#d`). The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be normalized. +```json +["d", "wss://history.nostr.watch/"] //tagId[] +``` +2. `"o" == tagOnline[0]` Is the relay online (`#o`). `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **should** be type string as exactly `true` or `false` +```json +["o", "true"] //tagOnline[] +``` +3. `"r" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **should** be type string as exactly `true` or `false` +```json +["r", "true"] //tagRead[] +``` +4. `"w" == tagWrite[0]` Was able to write to the relay. `tagWrite[]` **may** be included in the `event.tags[]` array. `tagWrite[1]` **should** be type string as exactly `true` or `false` +```json +["w", "false"] //tagWrite[] +``` +5. `"s" == tagSsl[0]` Is the relay's SSL valid (`#s`). `tagSsl[]` **may** be included in the `event.tags[]` array. `tagSsl[1]` **should** be type string as exactly `true` or `false` +```json +["s", "true"] //tagSSL[] +``` +6. `"t" == tagTopic[0]` Topics relavant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string +```json +["t", "bitcoin"] //tagTopic[] +``` +7. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string. There **may** be strings defined in the key range `2-6` (`tagGeo[2-6]`) and they **must** be strings if set. +```json +["g", "Europe", "NE", "Amsterdam", "52.377956", "4.897070"] //tagGeo[] +``` +8. `"x" == tagIPv4[0]` Relay IPv4. `tagIPv4[]` **may** be included in the `event.tags[]` array. `tagIPv4[1]` **must** be string. +```json +["x", "1.1.1.1"] //tagIPv4[] +``` +9. `"y" == tagIPv6[0]` Relay IPv6. `tagIPv6[]` **may** be included in the `event.tags[]` array. `tagIPv6[1]` **must** be string. +```json +["y", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIPv6[] +``` + +Example Event: +```json +{ + "id": "", + "pubkey": "", + "created_at": "", + "signature": "", + "content": "{}", + "tags": [ + ["d","wss://relay.snort.social/"], + ["o","true"], + ["r","true"], + ["w","false"], + ["s","true"], + ["t","bitcoin"], + ["t","nostrica"], + ["g","Europe","NE","Amsterdam","52.377956","4.897070"], + ["x", "1.1.1.1"], + ["y", "2001:db8:3333:4444:5555:6666:7777:8888"] + ] +} +``` + +### `event.content` _optional_ +The `.content` of these events **may** be empty. `.content` **may** contain stringified JSON. The parsed JSON has a flexible schema, all members are optional. The parsed `.content` JSON **should** be extended by NIPs. + +## Testing Criteria +The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between publishers. + +## Consumption +The data in `30303` **may** be erroneous, intentionally or otherwise. When accuracy is required, the data in `30303` events **should** be subscribed to by populating tthe `authors` filter array with the pubkeys of trusted **publishers** + +## Use Cases +- A lite social client identifies relays that were recently reported to be online without client-side tests +- A social client may find relays where a particular topic is popular. +- A social client may find relays based on their geographic proximity +- A status client shows relay statuses +- Identify macro-patterns amongst relays. +- Relays self-report statuses and/or metadata in `.content` signed by their NIP-11 `pubkey`. +- Could be used to store user checks for a relay to express personalized policies. For example, a user's pubkey was blacklisted on a relay, so they were unable to write: `..., tags: { [ ["d","wss://relay.damus.io"], ["o","true"], ["w","false"] ] }, ...`. From de9e41077ca2e44f2a08a0d0f47a9b2627c390d9 Mon Sep 17 00:00:00 2001 From: dskvr Date: Tue, 7 Feb 2023 15:12:03 +0100 Subject: [PATCH 02/34] A use case, fix text formatting --- 59.md | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/59.md b/59.md index 25942cc3..3786df5f 100644 --- a/59.md +++ b/59.md @@ -25,21 +25,21 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["d", "wss://history.nostr.watch/"] //tagId[] ``` -2. `"o" == tagOnline[0]` Is the relay online (`#o`). `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **should** be type string as exactly `true` or `false` +2. `"o" == tagOnline[0]` Is the relay online (`#o`). `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **must** be type string as exactly `true` or `false` ```json ["o", "true"] //tagOnline[] ``` -3. `"r" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **should** be type string as exactly `true` or `false` +3. `"r" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **must** be type string as exactly `true` or `false` ```json ["r", "true"] //tagRead[] ``` -4. `"w" == tagWrite[0]` Was able to write to the relay. `tagWrite[]` **may** be included in the `event.tags[]` array. `tagWrite[1]` **should** be type string as exactly `true` or `false` +4. `"w" == tagWrite[0]` Was able to write to the relay. `tagWrite[]` **may** be included in the `event.tags[]` array. `tagWrite[1]` **must** be type string as exactly `true` or `false` ```json ["w", "false"] //tagWrite[] ``` -5. `"s" == tagSsl[0]` Is the relay's SSL valid (`#s`). `tagSsl[]` **may** be included in the `event.tags[]` array. `tagSsl[1]` **should** be type string as exactly `true` or `false` +5. `"s" == tagSsl[0]` Is the relay's SSL valid. `tagSsl[]` **may** be included in the `event.tags[]` array. `tagSsl[1]` **must** be type string as exactly `true` or `false` ```json -["s", "true"] //tagSSL[] +["s", "true"] //tagSsl[] ``` 6. `"t" == tagTopic[0]` Topics relavant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string ```json @@ -58,11 +58,25 @@ The tags should be used to represent the Relay's abilities and meta at a point i ["y", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIPv6[] ``` +Minimal Requirements: +```json +{ + "id": "", + "pubkey": "", + "created_at": "", + "signature": "", + "content": "{}", + "tags": [ + ["d","wss://relay.snort.social/"] + ] +} +``` + Example Event: ```json { "id": "", - "pubkey": "", + "pubkey": "", "created_at": "", "signature": "", "content": "{}", @@ -88,9 +102,10 @@ The `.content` of these events **may** be empty. `.content` **may** contain stri The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between publishers. ## Consumption -The data in `30303` **may** be erroneous, intentionally or otherwise. When accuracy is required, the data in `30303` events **should** be subscribed to by populating tthe `authors` filter array with the pubkeys of trusted **publishers** +The data in `30303` **may** be erroneous, intentionally or otherwise. When accuracy is required, the data in `30303` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **publishers** ## Use Cases +- Aggregate relays quickly. - A lite social client identifies relays that were recently reported to be online without client-side tests - A social client may find relays where a particular topic is popular. - A social client may find relays based on their geographic proximity From 2a2fbc3202d371585224d7bc88a1bcf34a030cf2 Mon Sep 17 00:00:00 2001 From: dskvr Date: Tue, 7 Feb 2023 15:15:47 +0100 Subject: [PATCH 03/34] Consistent formatting --- 59.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/59.md b/59.md index 3786df5f..717de0d1 100644 --- a/59.md +++ b/59.md @@ -21,11 +21,11 @@ Relay status events have **two** (1) required tags and **eight** (8) optional ta The tags should be used to represent the Relay's abilities and meta at a point in time. Below the `tags schema` is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. -1. `"d" == tagId[0]` The relay URL (`#d`). The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be normalized. +1. `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be normalized. ```json ["d", "wss://history.nostr.watch/"] //tagId[] ``` -2. `"o" == tagOnline[0]` Is the relay online (`#o`). `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **must** be type string as exactly `true` or `false` +2. `"o" == tagOnline[0]` Is the relay online. `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **must** be type string as exactly `true` or `false` ```json ["o", "true"] //tagOnline[] ``` From 3bd4457997be3c9f4b79d5d9551a7ef3688866a8 Mon Sep 17 00:00:00 2001 From: dskvr Date: Tue, 7 Feb 2023 15:18:46 +0100 Subject: [PATCH 04/34] minimal -> minimum --- 59.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/59.md b/59.md index 717de0d1..72c2d07b 100644 --- a/59.md +++ b/59.md @@ -58,7 +58,7 @@ The tags should be used to represent the Relay's abilities and meta at a point i ["y", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIPv6[] ``` -Minimal Requirements: +Minimum Requirements: ```json { "id": "", From 1a154dc1c8d2361369c1023ef70e21c4b7698d10 Mon Sep 17 00:00:00 2001 From: dskvr Date: Tue, 7 Feb 2023 15:23:50 +0100 Subject: [PATCH 05/34] Fix typo --- 59.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/59.md b/59.md index 72c2d07b..da82c78b 100644 --- a/59.md +++ b/59.md @@ -41,7 +41,7 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["s", "true"] //tagSsl[] ``` -6. `"t" == tagTopic[0]` Topics relavant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string +6. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string ```json ["t", "bitcoin"] //tagTopic[] ``` From 2d10a628d8b292d0dc42f538be28c8ad2ce1cd04 Mon Sep 17 00:00:00 2001 From: dskvr Date: Fri, 10 Feb 2023 13:34:58 +0100 Subject: [PATCH 06/34] change schema --- 59.md | 57 +++++++++++++++++++++++++++------------------------------ 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/59.md b/59.md index da82c78b..e2d43f4b 100644 --- a/59.md +++ b/59.md @@ -25,54 +25,51 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["d", "wss://history.nostr.watch/"] //tagId[] ``` -2. `"o" == tagOnline[0]` Is the relay online. `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **must** be type string as exactly `true` or `false` +2. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string. There **should** be no more than **twenty (20)** `tagTopic[]` arrays. ```json -["o", "true"] //tagOnline[] +["t", "bitcoin"] //tagTopic[] ``` -3. `"r" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **must** be type string as exactly `true` or `false` +3. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string and **should** be a geohash. There **may** be strings defined in the key range `2+` (`tagGeo[2...]`) and they **must** be strings if set. `tagGeo[]` items **should** be ascending in terms of precision. There **should** be no more than **one (1)** `tagGeo[]` per event. ```json -["r", "true"] //tagRead[] +["g", "ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth", "Sol", "Milky Way"] //tagGeo[] ``` -4. `"w" == tagWrite[0]` Was able to write to the relay. `tagWrite[]` **may** be included in the `event.tags[]` array. `tagWrite[1]` **must** be type string as exactly `true` or `false` +4. `"online" == tagOnline[0]` Is the relay online. `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **must** be type string as exactly `true` or `false` ```json -["w", "false"] //tagWrite[] +["online", "true"] //tagOnline[] ``` -5. `"s" == tagSsl[0]` Is the relay's SSL valid. `tagSsl[]` **may** be included in the `event.tags[]` array. `tagSsl[1]` **must** be type string as exactly `true` or `false` +5. `"read" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **must** be type string as exactly `true` or `false` ```json -["s", "true"] //tagSsl[] +["read", "true"] //tagRead[] ``` -6. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string +6. `"write" == tagWrite[0]` Was able to write to the relay. `tagWrite[]` **may** be included in the `event.tags[]` array. `tagWrite[1]` **must** be type string as exactly `true` or `false` ```json -["t", "bitcoin"] //tagTopic[] +["write", "false"] //tagWrite[] ``` -7. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string. There **may** be strings defined in the key range `2-6` (`tagGeo[2-6]`) and they **must** be strings if set. +7. `"ssl" == tagSsl[0]` Is the relay's SSL valid. `tagSsl[]` **may** be included in the `event.tags[]` array. `tagSsl[1]` **must** be type string as exactly `true` or `false` ```json -["g", "Europe", "NE", "Amsterdam", "52.377956", "4.897070"] //tagGeo[] +["ssl", "true"] //tagSsl[] ``` -8. `"x" == tagIPv4[0]` Relay IPv4. `tagIPv4[]` **may** be included in the `event.tags[]` array. `tagIPv4[1]` **must** be string. +8. `"ip" == tagIp[0]` Relay IP. `ip[]` **may** be included in the `event.tags[]` array. `tagIp[1]` **must** be string. There **may** be more than one (1) `tagIp[]` ```json -["x", "1.1.1.1"] //tagIPv4[] -``` -9. `"y" == tagIPv6[0]` Relay IPv6. `tagIPv6[]` **may** be included in the `event.tags[]` array. `tagIPv6[1]` **must** be string. -```json -["y", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIPv6[] +["ip", "1.1.1.1"], //tagIp[] +["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[] ``` -Minimum Requirements: +Example with Minimum Requirements: ```json { "id": "", "pubkey": "", "created_at": "", "signature": "", - "content": "{}", + "content": "", "tags": [ ["d","wss://relay.snort.social/"] ] } ``` -Example Event: +Example with all Tags: ```json { "id": "", @@ -81,16 +78,16 @@ Example Event: "signature": "", "content": "{}", "tags": [ - ["d","wss://relay.snort.social/"], - ["o","true"], - ["r","true"], - ["w","false"], - ["s","true"], - ["t","bitcoin"], + ["d","wss://some.relay/"], ["t","nostrica"], - ["g","Europe","NE","Amsterdam","52.377956","4.897070"], - ["x", "1.1.1.1"], - ["y", "2001:db8:3333:4444:5555:6666:7777:8888"] + ["t","bitcoin"], + ["g","ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth"], + ["ip", "1.1.1.1"], + ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] + ["open","true"], + ["read","true"], + ["write","false"], + ["ssl","true"] ] } ``` From 24ed654e4c2fe1133a6d773310556d0c256b133d Mon Sep 17 00:00:00 2001 From: dskvr Date: Fri, 10 Feb 2023 13:44:30 +0100 Subject: [PATCH 07/34] asc -> desc --- 59.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/59.md b/59.md index e2d43f4b..b282eb5e 100644 --- a/59.md +++ b/59.md @@ -29,7 +29,7 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["t", "bitcoin"] //tagTopic[] ``` -3. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string and **should** be a geohash. There **may** be strings defined in the key range `2+` (`tagGeo[2...]`) and they **must** be strings if set. `tagGeo[]` items **should** be ascending in terms of precision. There **should** be no more than **one (1)** `tagGeo[]` per event. +3. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string and **should** be a geohash. There **may** be strings defined in the key range `2+` (`tagGeo[2...]`) and they **must** be strings if set. `tagGeo[]` items **should** be descending by precision. There **should** be no more than **one (1)** `tagGeo[]` per event. ```json ["g", "ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth", "Sol", "Milky Way"] //tagGeo[] ``` From 3c2f2c699780ea8f12f427fa06a3c917825f8f62 Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 11 Feb 2023 14:11:07 +0100 Subject: [PATCH 08/34] add two new tags and fix some small typos --- 59.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/59.md b/59.md index b282eb5e..d5d58a0f 100644 --- a/59.md +++ b/59.md @@ -17,7 +17,7 @@ To store relay meta-data and the result of subjective checks as queryable [NIP-1 `created_at` **should** be interpreted by consumers as `updated_at` ### `event.tags` -Relay status events have **two** (1) required tags and **eight** (8) optional tags. +Relay status events have **one** (1) required tags and **nine** (9) optional tags. The tags should be used to represent the Relay's abilities and meta at a point in time. Below the `tags schema` is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. @@ -49,12 +49,22 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["ssl", "true"] //tagSsl[] ``` -8. `"ip" == tagIp[0]` Relay IP. `ip[]` **may** be included in the `event.tags[]` array. `tagIp[1]` **must** be string. There **may** be more than one (1) `tagIp[]` +8. `"ip" == tagIp[0]` Relay IP. `tagIp[]` **may** be included in the `event.tags[]` array. `tagIp[1]` **must** be string. There **may** be more than one (1) `tagIp[]` ```json ["ip", "1.1.1.1"], //tagIp[] ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[] ``` +9. `"events" == tagEvents[0]` Number of events on relay. `tagEvents[]` **may** be included in the `event.tags[]` array. `tagEvents[1]` **must** be string. There **should** only be **one (1)** `tagEvents[]` +```json +["events", "502341"], //tagIp[] +``` + +10. `"users" == tagUsers[0]` Relay IP. `tagUsers[]` **may** be included in the `event.tags[]` array. `tagUsers[1]` **must** be string. There **should** be no more than **one (1)** `tagUsers[]` +```json +["users","37482"] +``` + Example with Minimum Requirements: ```json { From a86f7dcaaecbe611dcd21b7e54826b2f4c8e9827 Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 11 Feb 2023 14:12:09 +0100 Subject: [PATCH 09/34] add new tags to example --- 59.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/59.md b/59.md index d5d58a0f..7ce7cfb2 100644 --- a/59.md +++ b/59.md @@ -57,12 +57,12 @@ The tags should be used to represent the Relay's abilities and meta at a point i 9. `"events" == tagEvents[0]` Number of events on relay. `tagEvents[]` **may** be included in the `event.tags[]` array. `tagEvents[1]` **must** be string. There **should** only be **one (1)** `tagEvents[]` ```json -["events", "502341"], //tagIp[] +["events", "502341"], //tagEvents[] ``` 10. `"users" == tagUsers[0]` Relay IP. `tagUsers[]` **may** be included in the `event.tags[]` array. `tagUsers[1]` **must** be string. There **should** be no more than **one (1)** `tagUsers[]` ```json -["users","37482"] +["users","37482"] //tagUsers[] ``` Example with Minimum Requirements: @@ -97,7 +97,9 @@ Example with all Tags: ["open","true"], ["read","true"], ["write","false"], - ["ssl","true"] + ["ssl","true"], + ["events", "502341"], + ["users","37482"], ] } ``` From 649e40a0b34841b4a8f878a98008b751242d4a8a Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 11 Feb 2023 14:15:49 +0100 Subject: [PATCH 10/34] fix formatting --- 59.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/59.md b/59.md index 7ce7cfb2..f5725a54 100644 --- a/59.md +++ b/59.md @@ -92,8 +92,8 @@ Example with all Tags: ["t","nostrica"], ["t","bitcoin"], ["g","ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth"], - ["ip", "1.1.1.1"], - ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] + ["ip","1.1.1.1"], + ["ip","2001:db8:3333:4444:5555:6666:7777:8888"] ["open","true"], ["read","true"], ["write","false"], From 31675f04b43b5cfb44c6b0ea3679ab278ad13afb Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 11 Feb 2023 14:16:28 +0100 Subject: [PATCH 11/34] remove comma from last item in array --- 59.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/59.md b/59.md index f5725a54..1e29a3bd 100644 --- a/59.md +++ b/59.md @@ -99,7 +99,7 @@ Example with all Tags: ["write","false"], ["ssl","true"], ["events", "502341"], - ["users","37482"], + ["users","37482"] ] } ``` From 7bed3f722376b8a245d15782f1a067afa145f2ab Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 11 Feb 2023 14:27:08 +0100 Subject: [PATCH 12/34] missing comma --- 59.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/59.md b/59.md index 1e29a3bd..8863e2a5 100644 --- a/59.md +++ b/59.md @@ -93,7 +93,7 @@ Example with all Tags: ["t","bitcoin"], ["g","ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth"], ["ip","1.1.1.1"], - ["ip","2001:db8:3333:4444:5555:6666:7777:8888"] + ["ip","2001:db8:3333:4444:5555:6666:7777:8888"], ["open","true"], ["read","true"], ["write","false"], From 5c5f08c6acc437159d145523c377989da20bbc9c Mon Sep 17 00:00:00 2001 From: dskvr Date: Wed, 1 Mar 2023 17:51:26 +0100 Subject: [PATCH 13/34] update language as per discussion --- 59.md | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/59.md b/59.md index 8863e2a5..b088921d 100644 --- a/59.md +++ b/59.md @@ -5,38 +5,35 @@ This NIP defines `30303`, a parameterized replaceable event [NIP-33], referred to as Relay Statuses. Relay Statuses use tags extensively and **may** have `.content` populated with Stringified JSON. ## Purpose -To store relay meta-data and the result of subjective checks as queryable [NIP-12] events on nostr. +To store computationally expensive relay meta-data from active relays as events on nostr. ## Personas -- **Publishers** generate and push `30303` events. Events **should** be published at a regular interval. Events **may** be stale. +- **Publishers** generate and push `30303` events. Events **should** be published at a regular interval. Events **must** implement `NIP-40`. - **Consumers** aggregate `30303` for insight on relays. Some example consumers are a social client or relay status client. ## schema -### `event.created_at` -`created_at` **should** be interpreted by consumers as `updated_at` - ### `event.tags` -Relay status events have **one** (1) required tags and **nine** (9) optional tags. - +Relay status events have **two** (2) required tags and **eight** (8) optional tags. Relay status events introduce **one** (1) new indexable tag (NIP-12) + The tags should be used to represent the Relay's abilities and meta at a point in time. Below the `tags schema` is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. 1. `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be normalized. ```json ["d", "wss://history.nostr.watch/"] //tagId[] ``` -2. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string. There **should** be no more than **twenty (20)** `tagTopic[]` arrays. +2. `"expiration" == tagExpiration[0]` [NIP-40]. The `tagExpiration[]` tag **must** be included in the `event.tags[]` array. `tagExpiration[1]` **should** be set to a future timestamp that correlates with the publisher's intended update frequency. +```json +["expiration", "1600000000"] //tagExpiration[] +``` +3. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string. There **should** be no more than **twenty (20)** `tagTopic[]` arrays. ```json ["t", "bitcoin"] //tagTopic[] ``` -3. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string and **should** be a geohash. There **may** be strings defined in the key range `2+` (`tagGeo[2...]`) and they **must** be strings if set. `tagGeo[]` items **should** be descending by precision. There **should** be no more than **one (1)** `tagGeo[]` per event. +4. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string and **should** be a geohash. There **may** be strings defined in the key range `2+` (`tagGeo[2...]`) and they **must** be strings if set. `tagGeo[]` items **should** be descending by precision. There **should** be no more than **one (1)** `tagGeo[]` per event. ```json ["g", "ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth", "Sol", "Milky Way"] //tagGeo[] ``` -4. `"online" == tagOnline[0]` Is the relay online. `tagOnline[]` **may** be included in the `event.tags[]` array. `tagOnline[1]` **must** be type string as exactly `true` or `false` -```json -["online", "true"] //tagOnline[] -``` 5. `"read" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **must** be type string as exactly `true` or `false` ```json ["read", "true"] //tagRead[] @@ -54,17 +51,16 @@ The tags should be used to represent the Relay's abilities and meta at a point i ["ip", "1.1.1.1"], //tagIp[] ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[] ``` - 9. `"events" == tagEvents[0]` Number of events on relay. `tagEvents[]` **may** be included in the `event.tags[]` array. `tagEvents[1]` **must** be string. There **should** only be **one (1)** `tagEvents[]` ```json ["events", "502341"], //tagEvents[] ``` - 10. `"users" == tagUsers[0]` Relay IP. `tagUsers[]` **may** be included in the `event.tags[]` array. `tagUsers[1]` **must** be string. There **should** be no more than **one (1)** `tagUsers[]` ```json ["users","37482"] //tagUsers[] ``` + Example with Minimum Requirements: ```json { @@ -74,7 +70,8 @@ Example with Minimum Requirements: "signature": "", "content": "", "tags": [ - ["d","wss://relay.snort.social/"] + ["d","wss://relay.snort.social/"], + ["expiration", "1600000000"] ] } ``` @@ -89,12 +86,12 @@ Example with all Tags: "content": "{}", "tags": [ ["d","wss://some.relay/"], + ["expiration", "1600000000"], ["t","nostrica"], ["t","bitcoin"], - ["g","ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth"], + ["g","ww8p1r4t8","Amsterdam","NL","EU","Earth"], ["ip","1.1.1.1"], ["ip","2001:db8:3333:4444:5555:6666:7777:8888"], - ["open","true"], ["read","true"], ["write","false"], ["ssl","true"], @@ -111,7 +108,7 @@ The `.content` of these events **may** be empty. `.content` **may** contain stri The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between publishers. ## Consumption -The data in `30303` **may** be erroneous, intentionally or otherwise. When accuracy is required, the data in `30303` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **publishers** +The data in `30303` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30303` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **publishers** ## Use Cases - Aggregate relays quickly. @@ -119,6 +116,4 @@ The data in `30303` **may** be erroneous, intentionally or otherwise. When accur - A social client may find relays where a particular topic is popular. - A social client may find relays based on their geographic proximity - A status client shows relay statuses -- Identify macro-patterns amongst relays. - Relays self-report statuses and/or metadata in `.content` signed by their NIP-11 `pubkey`. -- Could be used to store user checks for a relay to express personalized policies. For example, a user's pubkey was blacklisted on a relay, so they were unable to write: `..., tags: { [ ["d","wss://relay.damus.io"], ["o","true"], ["w","false"] ] }, ...`. From 7316506d9748be6a55ae5ca68c9fd8a1f645caec Mon Sep 17 00:00:00 2001 From: dskvr Date: Wed, 1 Mar 2023 17:51:43 +0100 Subject: [PATCH 14/34] rename file --- 59.md => 66.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 59.md => 66.md (100%) diff --git a/59.md b/66.md similarity index 100% rename from 59.md rename to 66.md From 3b50d3d721e8a0cde70d0c4e756131624eeec5de Mon Sep 17 00:00:00 2001 From: dskvr Date: Wed, 1 Mar 2023 18:01:06 +0100 Subject: [PATCH 15/34] fix typo --- 66.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/66.md b/66.md index b088921d..2f960123 100644 --- a/66.md +++ b/66.md @@ -55,13 +55,13 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["events", "502341"], //tagEvents[] ``` -10. `"users" == tagUsers[0]` Relay IP. `tagUsers[]` **may** be included in the `event.tags[]` array. `tagUsers[1]` **must** be string. There **should** be no more than **one (1)** `tagUsers[]` +10. `"users" == tagUsers[0]` Number of users on relay. `tagUsers[]` **may** be included in the `event.tags[]` array. `tagUsers[1]` **must** be string. There **should** be no more than **one (1)** `tagUsers[]` ```json ["users","37482"] //tagUsers[] ``` -Example with Minimum Requirements: +Example with Minimum Requirements, "Relay is online" ```json { "id": "", @@ -76,7 +76,7 @@ Example with Minimum Requirements: } ``` -Example with all Tags: +Example with all Tags, "Relay is online and here's some data" ```json { "id": "", From 6c6251cfb26a1dbf751be16b08ad4ad3c357de44 Mon Sep 17 00:00:00 2001 From: dskvr Date: Wed, 1 Mar 2023 18:03:57 +0100 Subject: [PATCH 16/34] fix inconsistency in schema description --- 66.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/66.md b/66.md index 2f960123..28f77b5b 100644 --- a/66.md +++ b/66.md @@ -51,7 +51,7 @@ The tags should be used to represent the Relay's abilities and meta at a point i ["ip", "1.1.1.1"], //tagIp[] ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[] ``` -9. `"events" == tagEvents[0]` Number of events on relay. `tagEvents[]` **may** be included in the `event.tags[]` array. `tagEvents[1]` **must** be string. There **should** only be **one (1)** `tagEvents[]` +9. `"events" == tagEvents[0]` Number of events on relay. `tagEvents[]` **may** be included in the `event.tags[]` array. `tagEvents[1]` **must** be string. There **should** be no more than **one (1)** `tagEvents[]` ```json ["events", "502341"], //tagEvents[] ``` From 29a8acb69a8285e170f10cd47aec5d28f803fd50 Mon Sep 17 00:00:00 2001 From: dskvr Date: Wed, 12 Apr 2023 15:53:46 +0200 Subject: [PATCH 17/34] improve g tag and add language for IP data usage --- 66.md | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/66.md b/66.md index 28f77b5b..f7ef7b58 100644 --- a/66.md +++ b/66.md @@ -22,17 +22,20 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["d", "wss://history.nostr.watch/"] //tagId[] ``` -2. `"expiration" == tagExpiration[0]` [NIP-40]. The `tagExpiration[]` tag **must** be included in the `event.tags[]` array. `tagExpiration[1]` **should** be set to a future timestamp that correlates with the publisher's intended update frequency. +2. `"expiration" == tagExpiration[0]` [NIP-40]. The `tagExpiration[]` tag **must** be included in the `event.tags[]` array. `tagExpiration[1]` **should** be set to a future timestamp (seconds) that correlates with the publisher's intended update frequency. ```json ["expiration", "1600000000"] //tagExpiration[] ``` -3. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be string. There **should** be no more than **twenty (20)** `tagTopic[]` arrays. +3. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be a string. There **should** be no more than **fifty (50)** `tagTopic[]` arrays. ```json ["t", "bitcoin"] //tagTopic[] ``` -4. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string and **should** be a geohash. There **may** be strings defined in the key range `2+` (`tagGeo[2...]`) and they **must** be strings if set. `tagGeo[]` items **should** be descending by precision. There **should** be no more than **one (1)** `tagGeo[]` per event. +4. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string. `tagGeo[2]` **must** be a string and **should** be a label that describes `tagGeo[1]`. There **may** be more than **one (1)** `tagGeo[]` per event. ```json -["g", "ww8p1r4t8", "Amsterdam", "NL", "EU", "Earth", "Sol", "Milky Way"] //tagGeo[] + ["g","ww8p1r4t8","geohash"], + ["g","NL","countryCode"], + ["g","EU","continent"], + ["g","Earth","planet"] ``` 5. `"read" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **must** be type string as exactly `true` or `false` ```json @@ -46,7 +49,7 @@ The tags should be used to represent the Relay's abilities and meta at a point i ```json ["ssl", "true"] //tagSsl[] ``` -8. `"ip" == tagIp[0]` Relay IP. `tagIp[]` **may** be included in the `event.tags[]` array. `tagIp[1]` **must** be string. There **may** be more than one (1) `tagIp[]` +8. `"ip" == tagIp[0]` Relay IP. `tagIp[]` **may** be included in the `event.tags[]` array. `tagIp[1]` **must** be string. There **may** be more than one (1) `tagIp[]`. ```json ["ip", "1.1.1.1"], //tagIp[] ["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[] @@ -89,7 +92,10 @@ Example with all Tags, "Relay is online and here's some data" ["expiration", "1600000000"], ["t","nostrica"], ["t","bitcoin"], - ["g","ww8p1r4t8","Amsterdam","NL","EU","Earth"], + ["g","ww8p1r4t8","geohash"], + ["g","NL","countryCode"], + ["g","EU","continent"], + ["g","Earth","planet"], ["ip","1.1.1.1"], ["ip","2001:db8:3333:4444:5555:6666:7777:8888"], ["read","true"], @@ -108,10 +114,10 @@ The `.content` of these events **may** be empty. `.content` **may** contain stri The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between publishers. ## Consumption -The data in `30303` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30303` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **publishers** +The data in `30303` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30303` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **publishers**. **IP** data is for informational purposes only. ## Use Cases -- Aggregate relays quickly. +- Aggregate relays quickly using an implementation pattern native to nostr. - A lite social client identifies relays that were recently reported to be online without client-side tests - A social client may find relays where a particular topic is popular. - A social client may find relays based on their geographic proximity From 94da0c10148bf88212b2de5c0c98eb6051211371 Mon Sep 17 00:00:00 2001 From: dskvr Date: Wed, 27 Dec 2023 13:46:01 +0100 Subject: [PATCH 18/34] NIP-66 Winter-2023 Update --- 66.md | 334 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 245 insertions(+), 89 deletions(-) diff --git a/66.md b/66.md index f7ef7b58..983a69f3 100644 --- a/66.md +++ b/66.md @@ -1,70 +1,171 @@ -# NIP-59: Relay Status +# NIP-66: Relay Monitoring System -`draft` `optional` `author:dskvr` +`draft` `optional` -This NIP defines `30303`, a parameterized replaceable event [NIP-33], referred to as Relay Statuses. Relay Statuses use tags extensively and **may** have `.content` populated with Stringified JSON. +This NIP defines two event kinds, `30066` and `10066`. -## Purpose -To store computationally expensive relay meta-data from active relays as events on nostr. +## `10066`: "Relay Monitor" Events -## Personas -- **Publishers** generate and push `30303` events. Events **should** be published at a regular interval. Events **must** implement `NIP-40`. -- **Consumers** aggregate `30303` for insight on relays. Some example consumers are a social client or relay status client. +### Summary +`10066` is a replacable event herein referred to as "Relay Monitor" events. These events contain information about a publisher's intent to monitor and/or aggregate relays and publish data as `30066` events. -## schema +### Purpose +To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities. -### `event.tags` -Relay status events have **two** (2) required tags and **eight** (8) optional tags. Relay status events introduce **one** (1) new indexable tag (NIP-12) +### Schema +`10066` events have no required tags. + +- `"url" == tagUrl[0]` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's kind 0 for the pubkey that signed the `10066` event. + +- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is assumed the timeout provided applies to all tests. + +- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes 30066 events. + +#### Label Tags NIP-32 + +- `role`, for example: `checker` or `aggregator` + + _Checks but doesn't aggregate relay lists_ + ``` + [ 'L', 'role' ] + [ 'l', 'checker', 'role' ] + ``` + +- `checks`, should be a lowercase string describing the individual check if role is `checker`. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo` + + ``` + [ 'L', 'checks' ] + [ 'l', 'websocket', 'checks' ] + [ 'l', 'nip11', 'checks' ] + [ 'l', 'ssl', 'checks' ] + [ 'l', 'dns', 'checks' ] + [ 'l', 'geo', 'checks' ] + ``` + +### Other Requirements +- Monitors **should** have a published `10002` event that defines the relays the monitor publishes to. + +## `30066`: "Relay Status" Events + +### Summary +`30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay" event. These events store the existence and optionally some data relating to the relay. +a +### Purpose +To store useful, computationally expensive relay meta-data about relays. + + +### NIPs Used +- `NIP-32` Labels +- `NIP-33` Parameterized Replacable Events +- `NIP-40` Expirable Events +- "Yet Another Geo Tag" NIP (Draft) + +### Schema + +#### `event.content` +**Should** be empty. + +#### `event.tags` +Relay status events have **one** (1) required tag. -The tags should be used to represent the Relay's abilities and meta at a point in time. Below the `tags schema` is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. +Tags should be used to represent the Relay's abilities and meta at any given point in time. The "tags schema" is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. This NIP utilizes `NIP-32` to expose indexable values. -1. `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be normalized. -```json -["d", "wss://history.nostr.watch/"] //tagId[] -``` -2. `"expiration" == tagExpiration[0]` [NIP-40]. The `tagExpiration[]` tag **must** be included in the `event.tags[]` array. `tagExpiration[1]` **should** be set to a future timestamp (seconds) that correlates with the publisher's intended update frequency. -```json -["expiration", "1600000000"] //tagExpiration[] -``` -3. `"t" == tagTopic[0]` Topics relevant to the relay. `tagTopic[]` **may** be included in the `event.tags[]` array. `tagTopic[1]` **should** be a string. There **should** be no more than **fifty (50)** `tagTopic[]` arrays. -```json -["t", "bitcoin"] //tagTopic[] -``` -4. `"g" == tagGeo[0]` Relay Geo Data. `tagGeo[]` **may** be included in the `event.tags[]` array. `tagGeo[1]` **must** be string. `tagGeo[2]` **must** be a string and **should** be a label that describes `tagGeo[1]`. There **may** be more than **one (1)** `tagGeo[]` per event. -```json - ["g","ww8p1r4t8","geohash"], - ["g","NL","countryCode"], - ["g","EU","continent"], - ["g","Earth","planet"] -``` -5. `"read" == tagRead[0]` Was able to read from the relay. `tagRead[]` **may** be included in the `event.tags[]` array. `tagRead[1]` **must** be type string as exactly `true` or `false` -```json -["read", "true"] //tagRead[] -``` -6. `"write" == tagWrite[0]` Was able to write to the relay. `tagWrite[]` **may** be included in the `event.tags[]` array. `tagWrite[1]` **must** be type string as exactly `true` or `false` -```json -["write", "false"] //tagWrite[] -``` -7. `"ssl" == tagSsl[0]` Is the relay's SSL valid. `tagSsl[]` **may** be included in the `event.tags[]` array. `tagSsl[1]` **must** be type string as exactly `true` or `false` -```json -["ssl", "true"] //tagSsl[] -``` -8. `"ip" == tagIp[0]` Relay IP. `tagIp[]` **may** be included in the `event.tags[]` array. `tagIp[1]` **must** be string. There **may** be more than one (1) `tagIp[]`. -```json -["ip", "1.1.1.1"], //tagIp[] -["ip", "2001:db8:3333:4444:5555:6666:7777:8888"] //tagIp[] -``` -9. `"events" == tagEvents[0]` Number of events on relay. `tagEvents[]` **may** be included in the `event.tags[]` array. `tagEvents[1]` **must** be string. There **should** be no more than **one (1)** `tagEvents[]` -```json -["events", "502341"], //tagEvents[] -``` -10. `"users" == tagUsers[0]` Number of users on relay. `tagUsers[]` **may** be included in the `event.tags[]` array. `tagUsers[1]` **must** be string. There **should** be no more than **one (1)** `tagUsers[]` -```json -["users","37482"] //tagUsers[] -``` +#### Tags +- `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be normalized. + ``` + ["d", "wss://history.nostr.watch/"] //tagId[] + ``` + +- `"rtt-*" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags. + ``` + ["rtt", "open", "201", "190", "540"], + ["rtt", "read", "35", "60", "46"], + ["rtt", "write", "701", "497", "508"] + ``` + +- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via NIP-XX counts, via NIP-XX searches or other filters. There **may** be **0** to **many** count tags. + ``` + ["count", "total_events", "502341"], + ["count", "total_users", "52000"], + ["count", "active_users_24h", "321"] + ["count", "events_per_minute", "21.4"] + ``` + +- `"infohash" == tagInfohash[0]` A SHA256 hash of the deterministically stringified `NIP-11` "Info Document" JSON at `tagInfohash[1]` + +- `"notice" == tagNotice[0]` Special tag to display information about a relay. `tagNotice[1]` is a key to describe the notice. `tagNotice[2...]` **should** be the value(s) of the notice. There **may** be **0** to **many** notice tags. + +- `"expiration" === tagE[0]` An expiration timestamp to forcefully limit retention of relay events [`NIP-40`] + +- `"e" === tagE[0]` An association to another standard nostr event (`1000-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. The event referenced here **should** at a minimum be described in a draft NIP. + +#### Label Tags NIP-32 + +- `network`: Such as `clearnet`, `tor`, `i2p`, `cjdns`, etc. + ``` + [ 'L', 'network' ] + [ 'l', 'clearnet', 'network' ] + ``` + +- `relay_type`, for example `proxy`, `bridge` and `public` for example. There **may** be more than one type. + ``` + [ 'L', 'relay_type' ] + [ 'l', 'proxy', 'relay_type' ] + [ 'l', 'public', 'relay_type' ] + ``` + +- `ipv4` and `ipv6`, relay ips. + ``` + [ 'L', 'ipv4' ] + [ 'l', '1.1.1.1', 'ipv4' ] + [ 'L', 'ipv6' ] + [ 'l', '2001:db8:3333:4444:5555:6666:7777:8888"', 'ipv6' ] + ``` + +- Data from `NIP-11` using dot notation, for example + ``` + [ 'L', 'nip11.tags' ] + [ 'l', 'sfw-only' ] + [ 'l', 'bitcoin-only' ] + [ 'L', 'nip11.language_tags' ] + [ 'l', 'en', 'nip11.language_tags' ] + [ 'l', 'en-419', 'nip11.language_tags' ] + ``` + +#### Topic Tags +`NIP-66` leverages topics [`t` tags] for enumeration of nip support and NIP-11 boolean values + +- `supported_nips` from `NIP-11`, no leading zero. + ``` + [ 't', 'nip-1' ] + [ 't', 'nip-2' ] + [ 't', 'nip-9' ] + [ 't', 'nip-11' ] + ``` + +- For example `payment_required` and `auth_required` from `NIP-11.limitations` + ``` + [ 't', 'payment_required' ] + [ 't', 'auth_required' ] + ``` + +#### Methodology +A Checking Monitor publishes 30066 events exclusively when a relay is operational. This approach ensures that the last known state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics + +1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online. + +2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. They are responsible for setting and applying arbitrary thresholds to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor. + +3. For relay status events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics and performance, which might not be currently accessible due to the relay being offline. -Example with Minimum Requirements, "Relay is online" +#### Important Notes +- `NIP-11` values are provided as means to filter and discover relays, however **should not** be used as a replacement to `NIP-11`. +- A relay's retention policy could conflict with subjective thresholds used in determination of "online" or "dead" relays. + +#### Examples + +##### Minimum Requirements, "Relay was on a relay list" ```json { "id": "", @@ -73,53 +174,108 @@ Example with Minimum Requirements, "Relay is online" "signature": "", "content": "", "tags": [ - ["d","wss://relay.snort.social/"], - ["expiration", "1600000000"] + ["d","wss://some.relay/"] ] } ``` -Example with all Tags, "Relay is online and here's some data" +##### Minimum Requirements, "Relay was on a list but it might be a typo" ```json { "id": "", "pubkey": "", "created_at": "", "signature": "", - "content": "{}", + "content": "", "tags": [ - ["d","wss://some.relay/"], - ["expiration", "1600000000"], - ["t","nostrica"], - ["t","bitcoin"], - ["g","ww8p1r4t8","geohash"], - ["g","NL","countryCode"], - ["g","EU","continent"], - ["g","Earth","planet"], - ["ip","1.1.1.1"], - ["ip","2001:db8:3333:4444:5555:6666:7777:8888"], - ["read","true"], - ["write","false"], - ["ssl","true"], - ["events", "502341"], - ["users","37482"] + ["d","wdd://some.relay/"] + ["notice", "typo", "wss://some.relay/"] ] } ``` -### `event.content` _optional_ -The `.content` of these events **may** be empty. `.content` **may** contain stringified JSON. The parsed JSON has a flexible schema, all members are optional. The parsed `.content` JSON **should** be extended by NIPs. +##### Relay is checked and online example, "Relay is online and here's some meta-data this monitor believes is accurate" +```json +{ + "id": "", + "pubkey": "", + "created_at": "", + "signature": "", + "content": "{}", + "tags": [ + ["d","wss://some.relay/"], + ["rtt", "open", "201", "190", "540"], + ["rtt", "read", "35", "60", "46"], + ["rtt", "write", "701", "497", "508"], + ["ssl", "valid", "timestamp", "timestamp"], + ["count", "502341", "events"], + ["count", "21.4", "events_per_minute"], + ["L", "network"] + ["l", "clearnet", "network"] + ["g", "ww8p1r4t8","geohash"], + ["g","NL","countryCode"], + ["g","EU","continent"], + ["g","Earth","planet"], + ["L","ipv4"], + ["l","1.1.1.1""ipv4" ], + ["L","ipv6"], + ["l","2001:db8:3333:4444:5555:6666:7777:8888","ipv6"], + ["t", "nip-1"], + ["t", "nip-7"] + ] +} +``` -## Testing Criteria -The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between publishers. +##### Relay was checked and has been online, "Relay was online at _some_ point..." -## Consumption -The data in `30303` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30303` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **publishers**. **IP** data is for informational purposes only. +```json +{ + "id": "", + "pubkey": "", + "created_at": "", + "signature": "", + "content": "", + "tags": [ + ["d","wss://some.relay/"], + ["rtt", "open", "201", "190", "540"], + ["rtt", "read", "35", "60", "46"], + ["rtt", "write", "701", "497", "508"], + ... + ] +} +``` -## Use Cases -- Aggregate relays quickly using an implementation pattern native to nostr. -- A lite social client identifies relays that were recently reported to be online without client-side tests -- A social client may find relays where a particular topic is popular. -- A social client may find relays based on their geographic proximity -- A status client shows relay statuses -- Relays self-report statuses and/or metadata in `.content` signed by their NIP-11 `pubkey`. +#### Testing Criteria +The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between monitors. + +#### Limitations +The data in `30066` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **monitors** and where security is a concern any republished values (such as NIP-11 values) should be attained from the source. All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. + +#### Appending NIP-66 +Any test results that cannot be expressed through `NIP-66` **should** be ammended to the nip following discussion and general consensus + +### 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 Improvement Proposals (NIPs), ensuring compatibility with desired protocol features. + +3. **Accessibility Search**: Locate relays that are free to use, helping users find cost-effective or no-cost options for their network interactions. + +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, ensuring the accuracy and reliability of relay data. + +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. **Security and Compliance Checks**: Evaluate relays for adherence to security standards and regulatory compliance, essential for users with specific security and privacy requirements. + +9. **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. + +10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, and network types. + + +# Glossary +- `aggregate` the act of aggregating, qualifying, sanitizing and normalizing relays from relay lists to build a subjectively complete dataset of known relays. +- `check` the act of running tests on one or many attributes of a relay. \ No newline at end of file From 956f8251ac0fe0885eed96e74a9e7a77f2573e0d Mon Sep 17 00:00:00 2001 From: dskvr Date: Wed, 27 Dec 2023 13:55:16 +0100 Subject: [PATCH 19/34] dec-23 update --- 66.md | 247 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 133 insertions(+), 114 deletions(-) diff --git a/66.md b/66.md index 983a69f3..5902e93a 100644 --- a/66.md +++ b/66.md @@ -2,7 +2,7 @@ `draft` `optional` -This NIP defines two event kinds, `30066` and `10066`. +This NIP defines three event kinds, `10066`, `30066` and `1066`. ## `10066`: "Relay Monitor" Events @@ -17,31 +17,42 @@ To provide a directory of monitors, their intent to publish, their criteria and - `"url" == tagUrl[0]` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's kind 0 for the pubkey that signed the `10066` event. -- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is assumed the timeout provided applies to all tests. +- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is inferred that the timeout provided applies to all tests. + ``` + [ "timeout", "2000", "open" ] + [ "timeout", "2000", "read" ] + [ "timeout", "3000", "write" ] + [ "timeout", "2000", "info" ] + ``` -- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes 30066 events. +- `"kind === tagKind[0]"` The kind(s) this monitor publishes. + ``` + [ "kind", "30066" ] + [ "kind", "1066" ] + ``` + +- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded. + ``` + [ "frequency", "3600", "30066" ] + [ "frequency", "3600", "1066" ] + ``` #### Label Tags NIP-32 -- `role`, for example: `checker` or `aggregator` - - _Checks but doesn't aggregate relay lists_ - ``` - [ 'L', 'role' ] - [ 'l', 'checker', 'role' ] - ``` - -- `checks`, should be a lowercase string describing the individual check if role is `checker`. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo` +- `checks` **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo` ``` - [ 'L', 'checks' ] - [ 'l', 'websocket', 'checks' ] - [ 'l', 'nip11', 'checks' ] - [ 'l', 'ssl', 'checks' ] - [ 'l', 'dns', 'checks' ] - [ 'l', 'geo', 'checks' ] + [ "L", "checks" ] + [ "l", "websocket", "checks" ] + [ "l", "nip11", "checks" ] + [ "l", "ssl", "checks" ] + [ "l", "dns", "checks" ] + [ "l", "geo", "checks" ] ``` +#### Geo tags NIP-YAGT +- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) + ### Other Requirements - Monitors **should** have a published `10002` event that defines the relays the monitor publishes to. @@ -49,16 +60,15 @@ To provide a directory of monitors, their intent to publish, their criteria and ### Summary `30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay" event. These events store the existence and optionally some data relating to the relay. -a -### Purpose -To store useful, computationally expensive relay meta-data about relays. +### Purpose +To store useful, computationally expensive relay meta-data about relays. `30066` should be used to give a canonical reference to the last known functional state of a relay, to be evaluated subjectively by a client and/or user to derive conclusions from. ### NIPs Used - `NIP-32` Labels - `NIP-33` Parameterized Replacable Events - `NIP-40` Expirable Events -- "Yet Another Geo Tag" NIP (Draft) +- [YAGT](https://github.com/nostr-protocol/nips/pull/952) _draft_ ### Schema @@ -67,23 +77,37 @@ To store useful, computationally expensive relay meta-data about relays. #### `event.tags` Relay status events have **one** (1) required tag. + +Relay status events have **two** (2) non-standard, NIP-66 specific indexable tags. Tags should be used to represent the Relay's abilities and meta at any given point in time. The "tags schema" is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. This NIP utilizes `NIP-32` to expose indexable values. #### Tags -- `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be normalized. +- `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) ``` ["d", "wss://history.nostr.watch/"] //tagId[] ``` -- `"rtt-*" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags. +- `n`: Such as `clearnet`, `tor`, `i2p`, `cjdns`, etc _in the context of **NIP-66 only**_ + ``` + [ "n", "clearnet" ] + ``` + +- `N`: Supported NIPs _in the context of **NIP-66 only**_ + ``` + [ "N", "1" ] + [ "N", "11" ] + [ "N", "33" ] + ``` + +- `"rtt" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags. ``` ["rtt", "open", "201", "190", "540"], ["rtt", "read", "35", "60", "46"], ["rtt", "write", "701", "497", "508"] ``` +- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via NIP-XX counts, via NIP-XX searches or other filters. There **may** be zero (0) to many count tags. -- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via NIP-XX counts, via NIP-XX searches or other filters. There **may** be **0** to **many** count tags. ``` ["count", "total_events", "502341"], ["count", "total_users", "52000"], @@ -92,80 +116,98 @@ Tags should be used to represent the Relay's abilities and meta at any given poi ``` - `"infohash" == tagInfohash[0]` A SHA256 hash of the deterministically stringified `NIP-11` "Info Document" JSON at `tagInfohash[1]` + ``` + [ "infohash", "fj89as0n3inmcd89nefkdlsky2mfkdlsfds" ] + ``` -- `"notice" == tagNotice[0]` Special tag to display information about a relay. `tagNotice[1]` is a key to describe the notice. `tagNotice[2...]` **should** be the value(s) of the notice. There **may** be **0** to **many** notice tags. +- `"e" === tagE[0]` An association to another standard nostr event (`0/1/2/4-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. -- `"expiration" === tagE[0]` An expiration timestamp to forcefully limit retention of relay events [`NIP-40`] - -- `"e" === tagE[0]` An association to another standard nostr event (`1000-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. The event referenced here **should** at a minimum be described in a draft NIP. +- `"a" === tagE[0]` An association to another replaceable nostr event. An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. #### Label Tags NIP-32 - -- `network`: Such as `clearnet`, `tor`, `i2p`, `cjdns`, etc. +- `relay_type`, for example `proxy`, `bridge` and `public` for example. There **may** be more than one type. There have not been efforts to atomize relay types at the time of writing this NIPs, so these values cannot be enumerated at this time. ``` - [ 'L', 'network' ] - [ 'l', 'clearnet', 'network' ] + [ "L", "relay_type" ] + [ "l", "proxy", "relay_type" ] + [ "l", "public", "relay_type" ] ``` -- `relay_type`, for example `proxy`, `bridge` and `public` for example. There **may** be more than one type. +- `ipv4`/`ipv6`, relay ips. ``` - [ 'L', 'relay_type' ] - [ 'l', 'proxy', 'relay_type' ] - [ 'l', 'public', 'relay_type' ] + [ "L", "ipv4" ] + [ "l", "1.1.1.1", "ipv4" ] + [ "L", "ipv6" ] + [ "l", "2001:db8:3333:4444:5555:6666:7777:8888"", "ipv6" ] ``` -- `ipv4` and `ipv6`, relay ips. +- `as`/`asn` the relay ISPs "Autonomous System (Number)" ``` - [ 'L', 'ipv4' ] - [ 'l', '1.1.1.1', 'ipv4' ] - [ 'L', 'ipv6' ] - [ 'l', '2001:db8:3333:4444:5555:6666:7777:8888"', 'ipv6' ] + [ "as", "QUAD9-AS-1, CH" ] + [ "asn", "19281" ] ``` -- Data from `NIP-11` using dot notation, for example +- String values from `NIP-11` using dot notation, for example ``` - [ 'L', 'nip11.tags' ] - [ 'l', 'sfw-only' ] - [ 'l', 'bitcoin-only' ] - [ 'L', 'nip11.language_tags' ] - [ 'l', 'en', 'nip11.language_tags' ] - [ 'l', 'en-419', 'nip11.language_tags' ] + [ "L", "nip11.tags" ] + [ "l", "sfw-only" ] + [ "l", "bitcoin-only" ] + [ "L", "nip11.language_tags" ] + [ "l", "en", "nip11.language_tags" ] + [ "l", "en-419", "nip11.language_tags" ] + [ "L", "nip11.limitations" ] + ``` + +- Boolean values from `NIP-11`, for example + ``` + [ "L", "nip11.limitations" ] + [ "l", "payment_required", "nip11.limitations" ] //nip11.limitations.payment_required==true + [ "l", "auth_required", "nip11.limitations" ] //nip11.limitations.auth_required==true + ``` + +#### Geo tags NIP-YAGT +- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) + ``` + [ 'G', 'countryCode' ] + [ 'g', 'US', 'countryCode', 'alpha-2' ] + [ 'g', 'USA', 'countryCode', 'alpha-3' ] + [ 'g', '840', 'countryCode', 'numeric' ] + [ 'G', 'regionCode' ] + [ 'g', 'US-CA', 'regionCode'] + [ 'g', '9r1652whz' ] + [ 'g', '9r1652wh' ] + [ 'g', '9r1652w' ] + [ 'g', '9r1652' ] + [ 'g', '9r165' ] + [ 'g', '9r16' ] + [ 'g', '9r1' ] + [ 'g', '9r' ] + [ 'g', '9' ] ``` #### Topic Tags -`NIP-66` leverages topics [`t` tags] for enumeration of nip support and NIP-11 boolean values +- `NIP-66` leverages topics [`t` tags] and optionally adds values at positions `tag[2]` and `tag[3]`. If `tag[2]` is set, it **should** be a string-integer representing the number of tags on the relay. If `tag[2]` is set, `tag[3]` **should** be set and be a string-integer representing the timeframe for the value set as `tag[2]`. This tag is used to indicate topics relevant to the relay through event analysis (as oppossed to 'tags' from `NIP-11` document) -- `supported_nips` from `NIP-11`, no leading zero. ``` - [ 't', 'nip-1' ] - [ 't', 'nip-2' ] - [ 't', 'nip-9' ] - [ 't', 'nip-11' ] - ``` - -- For example `payment_required` and `auth_required` from `NIP-11.limitations` - ``` - [ 't', 'payment_required' ] - [ 't', 'auth_required' ] + //69 events with "meme" topic in the last hour + ["t", "meme", "69", "3600"] ``` #### Methodology -A Checking Monitor publishes 30066 events exclusively when a relay is operational. This approach ensures that the last known state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics +A Checking Monitor publishes 30066 events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics -1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online. +1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events using `since`. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online. -2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. They are responsible for setting and applying arbitrary thresholds to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor. +2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. The are responsible for setting and applying arbitrary thresholds using `until` filters to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor. 3. For relay status events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics and performance, which might not be currently accessible due to the relay being offline. - #### Important Notes - `NIP-11` values are provided as means to filter and discover relays, however **should not** be used as a replacement to `NIP-11`. -- A relay's retention policy could conflict with subjective thresholds used in determination of "online" or "dead" relays. +- A particular relay's retention policy could conflict with subjective thresholds used in determination of "online" or "dead" relays and so care should be taken with regards to chosen relays by both monitors and consumers. #### Examples -##### Minimum Requirements, "Relay was on a relay list" +##### Minimum Requirements, "Relay was online at `Date(created_at)`" ```json { "id": "", @@ -179,21 +221,6 @@ A Checking Monitor publishes 30066 events exclusively when a relay is operationa } ``` -##### Minimum Requirements, "Relay was on a list but it might be a typo" -```json -{ - "id": "", - "pubkey": "", - "created_at": "", - "signature": "", - "content": "", - "tags": [ - ["d","wdd://some.relay/"] - ["notice", "typo", "wss://some.relay/"] - ] -} -``` - ##### Relay is checked and online example, "Relay is online and here's some meta-data this monitor believes is accurate" ```json { @@ -212,44 +239,23 @@ A Checking Monitor publishes 30066 events exclusively when a relay is operationa ["count", "21.4", "events_per_minute"], ["L", "network"] ["l", "clearnet", "network"] - ["g", "ww8p1r4t8","geohash"], - ["g","NL","countryCode"], - ["g","EU","continent"], - ["g","Earth","planet"], - ["L","ipv4"], - ["l","1.1.1.1""ipv4" ], - ["L","ipv6"], - ["l","2001:db8:3333:4444:5555:6666:7777:8888","ipv6"], + ["g", "ww8p1r4t8"], + ["g", "NL", "countryCode", "alpha-2"], + ["L", "ipv4"], + ["l", "1.1.1.1""ipv4" ], + ["L", "ipv6"], + ["l", "2001:db8:3333:4444:5555:6666:7777:8888","ipv6"], ["t", "nip-1"], ["t", "nip-7"] ] } ``` -##### Relay was checked and has been online, "Relay was online at _some_ point..." - -```json -{ - "id": "", - "pubkey": "", - "created_at": "", - "signature": "", - "content": "", - "tags": [ - ["d","wss://some.relay/"], - ["rtt", "open", "201", "190", "540"], - ["rtt", "read", "35", "60", "46"], - ["rtt", "write", "701", "497", "508"], - ... - ] -} -``` - #### Testing Criteria The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between monitors. #### Limitations -The data in `30066` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **monitors** and where security is a concern any republished values (such as NIP-11 values) should be attained from the source. All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. +The data in `30066` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **monitors** and where security or privacy is a concern any republished values (such as NIP-11 values) should instead be attained from the source. All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. #### Appending NIP-66 Any test results that cannot be expressed through `NIP-66` **should** be ammended to the nip following discussion and general consensus @@ -273,9 +279,22 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende 9. **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. -10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, and network types. +10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. +## `1066`: "Relay Status History" Events -# Glossary -- `aggregate` the act of aggregating, qualifying, sanitizing and normalizing relays from relay lists to build a subjectively complete dataset of known relays. -- `check` the act of running tests on one or many attributes of a relay. \ No newline at end of file +### Summary +`1066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at a periodic interval (defined in `10066`). + +#### Schema +Relay History events can contain any of the tags defined for kind `30066` (Including the `d` tag which is used to filter these events by relay). There is one new indexable tag + +#### Special Considerations +- These events can potentially store a lot of data. + +#### Guidelines +Tags containd with this event should only be included when their values have changed compared to the last event. If there have been no changes, then the event should not be published. + +##### Use Cases +- Generate a time series from one or many data-point(s) for a specific relay. +- Generate network-wide aggregated statistics \ No newline at end of file From 1bc98b5cdbd074c69f27646438cb417a78837639 Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 30 Dec 2023 20:30:17 +0100 Subject: [PATCH 20/34] fix as/asn tags and verbage for 1066 --- 66.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/66.md b/66.md index 5902e93a..19c33ad0 100644 --- a/66.md +++ b/66.md @@ -142,8 +142,10 @@ Tags should be used to represent the Relay's abilities and meta at any given poi - `as`/`asn` the relay ISPs "Autonomous System (Number)" ``` - [ "as", "QUAD9-AS-1, CH" ] - [ "asn", "19281" ] + [ "L", "as" ] + [ "l", "QUAD9-AS-1, CH", "as" ] + [ "L", "asn" ] + [ "l", "19281", "asn" ] ``` - String values from `NIP-11` using dot notation, for example @@ -290,10 +292,10 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende Relay History events can contain any of the tags defined for kind `30066` (Including the `d` tag which is used to filter these events by relay). There is one new indexable tag #### Special Considerations -- These events can potentially store a lot of data. +- These events can potentially demand a lot of disk space if not used wisely. #### Guidelines -Tags containd with this event should only be included when their values have changed compared to the last event. If there have been no changes, then the event should not be published. +Tags representing less-volatile values, for instance `nip11.software` vs `rtt`, contained with this event should only be included when their respectiive values have changed compared to the last Relay History event of the same `d` tag. If there have been no changes, then the event should not be published. ##### Use Cases - Generate a time series from one or many data-point(s) for a specific relay. From 9a3c5c0230a38d4337153c720ae14fb1f0fd8c1d Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 30 Dec 2023 22:17:31 +0100 Subject: [PATCH 21/34] add self-reporting --- 66.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/66.md b/66.md index 19c33ad0..01f224f1 100644 --- a/66.md +++ b/66.md @@ -2,7 +2,7 @@ `draft` `optional` -This NIP defines three event kinds, `10066`, `30066` and `1066`. +This NIP defines four event kinds, `10066`, `30066`, `10066` and `1066`. ## `10066`: "Relay Monitor" Events @@ -106,7 +106,7 @@ Tags should be used to represent the Relay's abilities and meta at any given poi ["rtt", "read", "35", "60", "46"], ["rtt", "write", "701", "497", "508"] ``` -- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via NIP-XX counts, via NIP-XX searches or other filters. There **may** be zero (0) to many count tags. +- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. There **may** be zero (0) to many count tags. ``` ["count", "total_events", "502341"], @@ -283,6 +283,14 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende 10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. +## `10066`: "Self-Reported Relay Statuses" + +### Summary +A `30066` event with an `r` tag instead of a `d` tag. + +### Purpose +For relays to self-report + ## `1066`: "Relay Status History" Events ### Summary From b8b07a2659676d022026c190786069bddd95c553 Mon Sep 17 00:00:00 2001 From: dskvr Date: Sat, 30 Dec 2023 22:24:03 +0100 Subject: [PATCH 22/34] fix event kind collision --- 66.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/66.md b/66.md index 01f224f1..a3bceee9 100644 --- a/66.md +++ b/66.md @@ -2,7 +2,7 @@ `draft` `optional` -This NIP defines four event kinds, `10066`, `30066`, `10066` and `1066`. +This NIP defines four event kinds, `10066`, `30066`, `10166` and `1066`. ## `10066`: "Relay Monitor" Events @@ -283,7 +283,7 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende 10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. -## `10066`: "Self-Reported Relay Statuses" +## `10166`: "Self-Reported Relay Statuses" ### Summary A `30066` event with an `r` tag instead of a `d` tag. From 26ef08c90bf2ef56306ed75bdfb2b684e8aacf85 Mon Sep 17 00:00:00 2001 From: sandwich <299465+dskvr@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:52:48 +0100 Subject: [PATCH 23/34] reorganize kinds to be more intuitive --- 66.md | 204 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 113 insertions(+), 91 deletions(-) diff --git a/66.md b/66.md index a3bceee9..6098d251 100644 --- a/66.md +++ b/66.md @@ -1,89 +1,32 @@ -# NIP-66: Relay Monitoring System +# NIP-66: Relay Meta and Monitoring System `draft` `optional` This NIP defines four event kinds, `10066`, `30066`, `10166` and `1066`. -## `10066`: "Relay Monitor" Events - -### Summary -`10066` is a replacable event herein referred to as "Relay Monitor" events. These events contain information about a publisher's intent to monitor and/or aggregate relays and publish data as `30066` events. - -### Purpose -To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities. - -### Schema -`10066` events have no required tags. - -- `"url" == tagUrl[0]` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's kind 0 for the pubkey that signed the `10066` event. - -- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is inferred that the timeout provided applies to all tests. - ``` - [ "timeout", "2000", "open" ] - [ "timeout", "2000", "read" ] - [ "timeout", "3000", "write" ] - [ "timeout", "2000", "info" ] - ``` - -- `"kind === tagKind[0]"` The kind(s) this monitor publishes. - ``` - [ "kind", "30066" ] - [ "kind", "1066" ] - ``` - -- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded. - ``` - [ "frequency", "3600", "30066" ] - [ "frequency", "3600", "1066" ] - ``` - -#### Label Tags NIP-32 - -- `checks` **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo` - - ``` - [ "L", "checks" ] - [ "l", "websocket", "checks" ] - [ "l", "nip11", "checks" ] - [ "l", "ssl", "checks" ] - [ "l", "dns", "checks" ] - [ "l", "geo", "checks" ] - ``` - -#### Geo tags NIP-YAGT -- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) - -### Other Requirements -- Monitors **should** have a published `10002` event that defines the relays the monitor publishes to. - -## `30066`: "Relay Status" Events +## `10066`: "Self-Reported Relay Meta" + ### Summary -`30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay" event. These events store the existence and optionally some data relating to the relay. +An event that contains data about a relay. These events are self-reported by relays from the `owner` pubkey defined in their Information Document (`NIP-11`). Hereinafter referred to as "Relay Meta" events -### Purpose -To store useful, computationally expensive relay meta-data about relays. `30066` should be used to give a canonical reference to the last known functional state of a relay, to be evaluated subjectively by a client and/or user to derive conclusions from. +### Purpose +An event that makes relays discoverable. -### NIPs Used -- `NIP-32` Labels -- `NIP-33` Parameterized Replacable Events -- `NIP-40` Expirable Events -- [YAGT](https://github.com/nostr-protocol/nips/pull/952) _draft_ - -### Schema +## Schema #### `event.content` **Should** be empty. #### `event.tags` -Relay status events have **one** (1) required tag. +"Relay Meta" events have **one** (1) required tag. -Relay status events have **two** (2) non-standard, NIP-66 specific indexable tags. +"Relay Meta" events have **two** (2) non-standard, NIP-66 specific indexable tags. Tags should be used to represent the Relay's abilities and meta at any given point in time. The "tags schema" is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. This NIP utilizes `NIP-32` to expose indexable values. #### Tags -- `"d" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) +- `"r" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) ``` ["d", "wss://history.nostr.watch/"] //tagId[] ``` @@ -93,6 +36,11 @@ Tags should be used to represent the Relay's abilities and meta at any given poi [ "n", "clearnet" ] ``` +- `desc == tagDesc[0]` The description from nip11. + ``` + [ "desc", "A nostr relay" ] + ``` + - `N`: Supported NIPs _in the context of **NIP-66 only**_ ``` [ "N", "1" ] @@ -100,12 +48,6 @@ Tags should be used to represent the Relay's abilities and meta at any given poi [ "N", "33" ] ``` -- `"rtt" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags. - ``` - ["rtt", "open", "201", "190", "540"], - ["rtt", "read", "35", "60", "46"], - ["rtt", "write", "701", "497", "508"] - ``` - `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. There **may** be zero (0) to many count tags. ``` @@ -120,10 +62,6 @@ Tags should be used to represent the Relay's abilities and meta at any given poi [ "infohash", "fj89as0n3inmcd89nefkdlsky2mfkdlsfds" ] ``` -- `"e" === tagE[0]` An association to another standard nostr event (`0/1/2/4-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. - -- `"a" === tagE[0]` An association to another replaceable nostr event. An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. - #### Label Tags NIP-32 - `relay_type`, for example `proxy`, `bridge` and `public` for example. There **may** be more than one type. There have not been efforts to atomize relay types at the time of writing this NIPs, so these values cannot be enumerated at this time. ``` @@ -156,7 +94,6 @@ Tags should be used to represent the Relay's abilities and meta at any given poi [ "L", "nip11.language_tags" ] [ "l", "en", "nip11.language_tags" ] [ "l", "en-419", "nip11.language_tags" ] - [ "L", "nip11.limitations" ] ``` - Boolean values from `NIP-11`, for example @@ -194,12 +131,48 @@ Tags should be used to represent the Relay's abilities and meta at any given poi ["t", "meme", "69", "3600"] ``` +## `30066`: "Relay Status" Events + +### Summary +`30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay Status" event. These events store the existence and optionally some data relating to the relay. + +### Purpose +To store useful, computationally expensive relay meta-data about relays. `30066` should be used to give a canonical reference to the last known functional state of a relay, to be evaluated subjectively by a client and/or user to derive conclusions from. + +### NIPs Used +- `NIP-32` Labels +- `NIP-33` Parameterized Replacable Events +- `NIP-40` Expirable Events +- [YAGT](https://github.com/nostr-protocol/nips/pull/952) _draft_ + +### Schema +`30066` events are almost identical to `10066` except a few key differences. + +_**Different referencial tag**_ + +- `30066` uses a `d` tag instead of an `r` tag for the normalized relay URL since it is a Parameterized-Replaceable Event + +_**It adds some additional tags**_ + +- `"rtt" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags. + + ``` + ["rtt", "open", "201", "190", "540"], + ["rtt", "read", "35", "60", "46"], + ["rtt", "write", "701", "497", "508"] + ``` + +- `"e" === tagE[0]` An association to another standard nostr event (`0/1/2/4-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. + +- `"a" === tagE[0]` An association to another replaceable nostr event. An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. + + #### Methodology -A Checking Monitor publishes 30066 events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics +A Relay Monitor publishes `30066`` events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics 1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events using `since`. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online. -2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. The are responsible for setting and applying arbitrary thresholds using `until` filters to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor. +2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. The are responsible for setting and applying arbitrary thresholds using `until` filters or post-processing to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor. 3. For relay status events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics and performance, which might not be currently accessible due to the relay being offline. @@ -233,6 +206,8 @@ A Checking Monitor publishes 30066 events exclusively when a relay is operationa "content": "{}", "tags": [ ["d","wss://some.relay/"], + ["N", "1"], + ["N", "7"], ["rtt", "open", "201", "190", "540"], ["rtt", "read", "35", "60", "46"], ["rtt", "write", "701", "497", "508"], @@ -246,9 +221,7 @@ A Checking Monitor publishes 30066 events exclusively when a relay is operationa ["L", "ipv4"], ["l", "1.1.1.1""ipv4" ], ["L", "ipv6"], - ["l", "2001:db8:3333:4444:5555:6666:7777:8888","ipv6"], - ["t", "nip-1"], - ["t", "nip-7"] + ["l", "2001:db8:3333:4444:5555:6666:7777:8888", "ipv6"] ] } ``` @@ -283,18 +256,67 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende 10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. -## `10166`: "Self-Reported Relay Statuses" - -### Summary -A `30066` event with an `r` tag instead of a `d` tag. +## `10166`: "Relay Monitor" Events -### Purpose -For relays to self-report +### Summary +`10166` is a replacable event herein referred to as "Relay Monitor" events. These events contain information about a publisher's intent to monitor and/or aggregate relays and publish data as `30066` events. + +### Purpose +To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities. + +### Schema +`10166` events have no required tags. + +- `"url" == tagUrl[0]` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's kind 0 for the pubkey that signed the `10066` event. + +- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is inferred that the timeout provided applies to all tests. + ``` + [ "timeout", "2000", "open" ] + [ "timeout", "2000", "read" ] + [ "timeout", "3000", "write" ] + [ "timeout", "2000", "info" ] + ``` + +- `"ssl" == tagSsl[0]` SSL certificate check. `tag[1]` is either `valid` or `invalid`. `tag[2]` is the validate start date. `tag[3]` is the validity end date. Can include reference via `e` or `a` to raw SSL data for indepdent validation. + ``` + ["ssl", "valid", "timestamp", "timestamp"], + ``` + +- `"kind === tagKind[0]"` The kind(s) this monitor publishes. + ``` + [ "kind", "30066" ] + [ "kind", "1066" ] + ``` + +- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded. + ``` + [ "frequency", "3600", "30066" ] + [ "frequency", "3600", "1066" ] + ``` + +#### Label Tags NIP-32 + +- `checks` **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo` + + ``` + [ "L", "checks" ] + [ "l", "websocket", "checks" ] + [ "l", "nip11", "checks" ] + [ "l", "ssl", "checks" ] + [ "l", "dns", "checks" ] + [ "l", "geo", "checks" ] + ``` + +#### Geo tags NIP-YAGT +- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) + +### Other Requirements +- Monitors **should** have a published `10002` event that defines the relays the monitor publishes to. ## `1066`: "Relay Status History" Events ### Summary -`1066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at a periodic interval (defined in `10066`). +`1066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at a periodic interval (defined in `10166`). #### Schema Relay History events can contain any of the tags defined for kind `30066` (Including the `d` tag which is used to filter these events by relay). There is one new indexable tag @@ -306,5 +328,5 @@ Relay History events can contain any of the tags defined for kind `30066` (Inclu Tags representing less-volatile values, for instance `nip11.software` vs `rtt`, contained with this event should only be included when their respectiive values have changed compared to the last Relay History event of the same `d` tag. If there have been no changes, then the event should not be published. ##### Use Cases -- Generate a time series from one or many data-point(s) for a specific relay. +- Generate a time series from one or data-point(s) for a specific relay. - Generate network-wide aggregated statistics \ No newline at end of file From 913dd3a018bb739b0a52e3976afc95d57e6af159 Mon Sep 17 00:00:00 2001 From: sandwich <299465+dskvr@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:17:28 +0000 Subject: [PATCH 24/34] Fix formatting --- 66.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/66.md b/66.md index 6098d251..62647120 100644 --- a/66.md +++ b/66.md @@ -13,7 +13,7 @@ An event that contains data about a relay. These events are self-reported by rel ### Purpose An event that makes relays discoverable. -## Schema +### Schema #### `event.content` **Should** be empty. @@ -89,8 +89,8 @@ Tags should be used to represent the Relay's abilities and meta at any given poi - String values from `NIP-11` using dot notation, for example ``` [ "L", "nip11.tags" ] - [ "l", "sfw-only" ] - [ "l", "bitcoin-only" ] + [ "l", "sfw-only", "nip11.tags" ] + [ "l", "bitcoin-only", "nip11.tags" ] [ "L", "nip11.language_tags" ] [ "l", "en", "nip11.language_tags" ] [ "l", "en-419", "nip11.language_tags" ] @@ -162,10 +162,6 @@ _**It adds some additional tags**_ ["rtt", "write", "701", "497", "508"] ``` -- `"e" === tagE[0]` An association to another standard nostr event (`0/1/2/4-9999` kind-range). An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. - -- `"a" === tagE[0]` An association to another replaceable nostr event. An example would be an event containing the most recent check log or an archival event representing the check. Such a reference may contain duplicate or ommitted tags from a `30066` event. - #### Methodology A Relay Monitor publishes `30066`` events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics From 154ffc1a84bcc3aa3603e74770f0edf26823831c Mon Sep 17 00:00:00 2001 From: sandwich <299465+dskvr@users.noreply.github.com> Date: Tue, 23 Jan 2024 18:52:27 +0000 Subject: [PATCH 25/34] changes --- 66.md | 1 + 1 file changed, 1 insertion(+) diff --git a/66.md b/66.md index 62647120..66da811b 100644 --- a/66.md +++ b/66.md @@ -213,6 +213,7 @@ A Relay Monitor publishes `30066`` events exclusively when a relay is operationa ["L", "network"] ["l", "clearnet", "network"] ["g", "ww8p1r4t8"], + ["G", "countryCode"] ["g", "NL", "countryCode", "alpha-2"], ["L", "ipv4"], ["l", "1.1.1.1""ipv4" ], From 2db9908166a83642d067d473a8953a1da828c031 Mon Sep 17 00:00:00 2001 From: sandwich <299465+dskvr@users.noreply.github.com> Date: Tue, 23 Jan 2024 19:46:42 +0000 Subject: [PATCH 26/34] limitations->limitation fix, integer solution, nested obj disclaimed --- 66.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/66.md b/66.md index 66da811b..dccbec9e 100644 --- a/66.md +++ b/66.md @@ -98,11 +98,21 @@ Tags should be used to represent the Relay's abilities and meta at any given poi - Boolean values from `NIP-11`, for example ``` - [ "L", "nip11.limitations" ] - [ "l", "payment_required", "nip11.limitations" ] //nip11.limitations.payment_required==true - [ "l", "auth_required", "nip11.limitations" ] //nip11.limitations.auth_required==true + [ "L", "nip11.limitation" ] + [ "l", "payment_required", "nip11.limitation" ] //nip11.limitation payment_required==true + [ "l", "auth_required", "nip11.limitation" ] //nip11.limitation auth_required==true ``` +#### NIP-11 Integer Values +Any NIP-11 values that are integers should not be included as NIP-32 labels, instead they should use the `nip11` tag. + +``` +[ "nip11", "65535", "limitation.max_message_length" ] +``` + +#### NIP-11 Nested Objects +NIP-11 nested objects are not supported by NIP-66 at this time (For example, fees) + #### Geo tags NIP-YAGT - `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) ``` From 41feba2746db8d8d002117ec10459a471c67e8fa Mon Sep 17 00:00:00 2001 From: sandwich <299465+dskvr@users.noreply.github.com> Date: Tue, 23 Jan 2024 19:55:39 +0000 Subject: [PATCH 27/34] fix mismatch between schema and example --- 66.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/66.md b/66.md index dccbec9e..2c8c615c 100644 --- a/66.md +++ b/66.md @@ -212,23 +212,28 @@ A Relay Monitor publishes `30066`` events exclusively when a relay is operationa "content": "{}", "tags": [ ["d","wss://some.relay/"], + ["n", "clearnet"] ["N", "1"], ["N", "7"], ["rtt", "open", "201", "190", "540"], ["rtt", "read", "35", "60", "46"], ["rtt", "write", "701", "497", "508"], ["ssl", "valid", "timestamp", "timestamp"], - ["count", "502341", "events"], ["count", "21.4", "events_per_minute"], - ["L", "network"] - ["l", "clearnet", "network"] ["g", "ww8p1r4t8"], ["G", "countryCode"] - ["g", "NL", "countryCode", "alpha-2"], + ["g", "NL", "countryCode"], ["L", "ipv4"], - ["l", "1.1.1.1""ipv4" ], + ["l", "1.1.1.1", "ipv4" ], ["L", "ipv6"], - ["l", "2001:db8:3333:4444:5555:6666:7777:8888", "ipv6"] + ["l", "2001:db8:3333:4444:5555:6666:7777:8888", "ipv6"], + ["L", "nip11.tags" ], + ["l", "sfw-only", "nip11.tags" ], + ["l", "bitcoin-only", "nip11.tags" ] + ["L", "nip11.language_tags" ], + ["l", "en", "nip11.language_tags" ], + ["l", "en-419", "nip11.language_tags" ], + ["nip11", "65535", "limitation.max_message_length" ] ] } ``` From be0ebd5b34acb42e51739063177f56e50d3befb1 Mon Sep 17 00:00:00 2001 From: sandwich <299465+dskvr@users.noreply.github.com> Date: Thu, 25 Jan 2024 20:12:03 +0000 Subject: [PATCH 28/34] Fix some typos, improve language, add example 1066 event --- 66.md | 112 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 76 insertions(+), 36 deletions(-) diff --git a/66.md b/66.md index 2c8c615c..0f310e36 100644 --- a/66.md +++ b/66.md @@ -4,14 +4,19 @@ This NIP defines four event kinds, `10066`, `30066`, `10166` and `1066`. +## Table of Contents +- `10066` [Self-reported Relay Meta](#k10066) +- `30066` [Monitor Relay Meta & Status](#k30066) +- `10166` [Monitor Meta Data](#k10166) +- `1066` [Historical Relay Meta](#k1066) -## `10066`: "Self-Reported Relay Meta" +## `10066`: "Self-Reported Relay Meta" ### Summary An event that contains data about a relay. These events are self-reported by relays from the `owner` pubkey defined in their Information Document (`NIP-11`). Hereinafter referred to as "Relay Meta" events ### Purpose -An event that makes relays discoverable. +An event published by a relay owner that makes the owner's relay discoverable. ### Schema @@ -19,9 +24,9 @@ An event that makes relays discoverable. **Should** be empty. #### `event.tags` -"Relay Meta" events have **one** (1) required tag. +"Self-Reported Relay Meta" events have **one** (1) required tag. -"Relay Meta" events have **two** (2) non-standard, NIP-66 specific indexable tags. +"Self-Reported Relay Meta" events have **two** (2) non-standard, NIP-66 specific indexable tags. Tags should be used to represent the Relay's abilities and meta at any given point in time. The "tags schema" is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. This NIP utilizes `NIP-32` to expose indexable values. @@ -36,7 +41,12 @@ Tags should be used to represent the Relay's abilities and meta at any given poi [ "n", "clearnet" ] ``` -- `desc == tagDesc[0]` The description from nip11. +- `desc == tagDesc[0]` The `description` from relay's NIP-11 information document. + ``` + [ "desc", "A nostr relay" ] + ``` + +- `name == tagname[0]` The `name` member from relay's NIP-11 information document. ``` [ "desc", "A nostr relay" ] ``` @@ -48,22 +58,22 @@ Tags should be used to represent the Relay's abilities and meta at any given poi [ "N", "33" ] ``` -- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. There **may** be zero (0) to many count tags. +- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. A count's key should be **snake case**. There **may** be zero (0) to many count tags. ``` - ["count", "total_events", "502341"], - ["count", "total_users", "52000"], - ["count", "active_users_24h", "321"] - ["count", "events_per_minute", "21.4"] + ["count", "502341", "total_events"], + ["count", "52000", "total_users"], + ["count", "321", "active_users_24h"] + ["count", "21.4", "events_per_minute"] ``` - `"infohash" == tagInfohash[0]` A SHA256 hash of the deterministically stringified `NIP-11` "Info Document" JSON at `tagInfohash[1]` ``` - [ "infohash", "fj89as0n3inmcd89nefkdlsky2mfkdlsfds" ] + [ "infohash", "8332f76d1fbbd3c83abc8eeb5cac296fb7514b9b06d8734f98c16c246d6ec590" ] ``` #### Label Tags NIP-32 -- `relay_type`, for example `proxy`, `bridge` and `public` for example. There **may** be more than one type. There have not been efforts to atomize relay types at the time of writing this NIPs, so these values cannot be enumerated at this time. +- `relay_type`, for example `proxy`, `bridge` and `public`. There **may** be more than one type. _Please note,_ at time of writing there has been no collective effort to atomize relay types, so these values cannot be enumerated. ``` [ "L", "relay_type" ] [ "l", "proxy", "relay_type" ] @@ -104,7 +114,7 @@ Tags should be used to represent the Relay's abilities and meta at any given poi ``` #### NIP-11 Integer Values -Any NIP-11 values that are integers should not be included as NIP-32 labels, instead they should use the `nip11` tag. +Any NIP-11 values that are integers **should not** be included as NIP-32 labels, instead NIP-11 integer vlaues should use the `nip11` tag. ``` [ "nip11", "65535", "limitation.max_message_length" ] @@ -117,9 +127,9 @@ NIP-11 nested objects are not supported by NIP-66 at this time (For example, fee - `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) ``` [ 'G', 'countryCode' ] - [ 'g', 'US', 'countryCode', 'alpha-2' ] - [ 'g', 'USA', 'countryCode', 'alpha-3' ] - [ 'g', '840', 'countryCode', 'numeric' ] + [ 'g', 'US', 'countryCode'] + [ 'g', 'USA', 'countryCode' ] + [ 'g', '840', 'countryCode' ] [ 'G', 'regionCode' ] [ 'g', 'US-CA', 'regionCode'] [ 'g', '9r1652whz' ] @@ -134,14 +144,13 @@ NIP-11 nested objects are not supported by NIP-66 at this time (For example, fee ``` #### Topic Tags -- `NIP-66` leverages topics [`t` tags] and optionally adds values at positions `tag[2]` and `tag[3]`. If `tag[2]` is set, it **should** be a string-integer representing the number of tags on the relay. If `tag[2]` is set, `tag[3]` **should** be set and be a string-integer representing the timeframe for the value set as `tag[2]`. This tag is used to indicate topics relevant to the relay through event analysis (as oppossed to 'tags' from `NIP-11` document) +- `NIP-66` leverages topics [`t` tags] and optionally adds values at positions `tag[2]` and `tag[3]`. If `tag[2]` is set, it **should** be a string-integer representing the number of tags on the relay. If `tag[2]` is set, `tag[3]` **should** be set and be a string-integer representing the timeframe **in seconds** for the value set as `tag[2]`. This tag is used to indicate topics relevant to the relay through event analysis (as oppossed to 'tags' from `NIP-11` document) ``` - //69 events with "meme" topic in the last hour ["t", "meme", "69", "3600"] ``` -## `30066`: "Relay Status" Events +## `30066`: "Relay Status" Events ### Summary `30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay Status" event. These events store the existence and optionally some data relating to the relay. @@ -156,7 +165,7 @@ To store useful, computationally expensive relay meta-data about relays. `30066` - [YAGT](https://github.com/nostr-protocol/nips/pull/952) _draft_ ### Schema -`30066` events are almost identical to `10066` except a few key differences. +`30066` inherit the schema from `10066`, with a substitution and some additional tags. _**Different referencial tag**_ @@ -172,7 +181,6 @@ _**It adds some additional tags**_ ["rtt", "write", "701", "497", "508"] ``` - #### Methodology A Relay Monitor publishes `30066`` events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics @@ -196,6 +204,7 @@ A Relay Monitor publishes `30066`` events exclusively when a relay is operationa "created_at": "", "signature": "", "content": "", + "kind": 30066, "tags": [ ["d","wss://some.relay/"] ] @@ -210,6 +219,7 @@ A Relay Monitor publishes `30066`` events exclusively when a relay is operationa "created_at": "", "signature": "", "content": "{}", + "kind": 30066, "tags": [ ["d","wss://some.relay/"], ["n", "clearnet"] @@ -242,9 +252,9 @@ A Relay Monitor publishes `30066`` events exclusively when a relay is operationa The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between monitors. #### Limitations -The data in `30066` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **should** be subscribed to by populating the `authors` filter array with the pubkeys of trusted **monitors** and where security or privacy is a concern any republished values (such as NIP-11 values) should instead be attained from the source. All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. +The data in `30066` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **should** be subscribed to by populating the `authors` filter array with the poublic keys of trusted **monitors** and where security or privacy is a concern any republished values (such as NIP-11 values) should instead be attained from the source. All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. -#### Appending NIP-66 +#### Ammending NIP-66 Any test results that cannot be expressed through `NIP-66` **should** be ammended to the nip following discussion and general consensus ### Use Cases @@ -268,7 +278,7 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende 10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. -## `10166`: "Relay Monitor" Events +## `10166`: "Relay Monitor" Events ### Summary `10166` is a replacable event herein referred to as "Relay Monitor" events. These events contain information about a publisher's intent to monitor and/or aggregate relays and publish data as `30066` events. @@ -286,12 +296,7 @@ To provide a directory of monitors, their intent to publish, their criteria and [ "timeout", "2000", "open" ] [ "timeout", "2000", "read" ] [ "timeout", "3000", "write" ] - [ "timeout", "2000", "info" ] - ``` - -- `"ssl" == tagSsl[0]` SSL certificate check. `tag[1]` is either `valid` or `invalid`. `tag[2]` is the validate start date. `tag[3]` is the validity end date. Can include reference via `e` or `a` to raw SSL data for indepdent validation. - ``` - ["ssl", "valid", "timestamp", "timestamp"], + [ "timeout", "2000", "nip11" ] ``` - `"kind === tagKind[0]"` The kind(s) this monitor publishes. @@ -300,7 +305,7 @@ To provide a directory of monitors, their intent to publish, their criteria and [ "kind", "1066" ] ``` -- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded. +- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency **in seconds** a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded. ``` [ "frequency", "3600", "30066" ] [ "frequency", "3600", "1066" ] @@ -320,18 +325,53 @@ To provide a directory of monitors, their intent to publish, their criteria and ``` #### Geo tags NIP-YAGT -- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) +- Kind `10166` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) ### Other Requirements -- Monitors **should** have a published `10002` event that defines the relays the monitor publishes to. +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. -## `1066`: "Relay Status History" Events +### Example +```json +{ + "id": "", + "pubkey": "", + "created_at": "", + "signature": "", + "content": "{}", + "tags": [ + [ "url", "wss://bob.some.guy"], + + [ "L", "checks" ], + [ "l", "websocket", "checks" ], + [ "l", "nip11", "checks" ], + + [ "kind", "30066" ], + [ "kind", "1066" ], + + [ "frequency", "3600", "30066" ], + [ "frequency", "3600", "1066" ], + + [ "timeout", "5000", "open" ], + [ "timeout", "3000", "read" ], + [ "timeout", "3000", "write" ], + [ "timeout", "2000", "nip11" ], + + ["g", "ww8p1r4t8"], + ["G", "countryCode"], + ["g", "NL", "countryCode"] + ] +} +``` + +## `1066`: "Relay Status History" Events ### Summary -`1066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at a periodic interval (defined in `10166`). +`3066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at the periodic interval defined in the monitor's `10166`. #### Schema -Relay History events can contain any of the tags defined for kind `30066` (Including the `d` tag which is used to filter these events by relay). There is one new indexable tag +Relay History events can contain any of the tags defined for kind `30066`. The `d` tag should be included in every `3066` event, as it can be used to filter historical events by relay URL. #### Special Considerations - These events can potentially demand a lot of disk space if not used wisely. From f83c49fc3977fb4fcbf409ce6da3a2a4f2bb31ad Mon Sep 17 00:00:00 2001 From: sandwich <299465+dskvr@users.noreply.github.com> Date: Thu, 8 Feb 2024 00:32:22 +0000 Subject: [PATCH 29/34] draft6 --- 66.md | 696 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 406 insertions(+), 290 deletions(-) diff --git a/66.md b/66.md index 0f310e36..5893bddc 100644 --- a/66.md +++ b/66.md @@ -2,201 +2,422 @@ `draft` `optional` -This NIP defines four event kinds, `10066`, `30066`, `10166` and `1066`. +## Table of Kinds +This NIP defines three (3) event kinds, `30066`, `30166` and `10166` +| kind | name | description | +|-------|----------------------------|-----------------------------------------------------------------------------------------| +| [10166](#k10166) | Relay Monitor Registration | An RE that stores data to publish intent to monitor and details around their activities | +| [30166](#k30166) | Relay Discoverability | A PRE composed of only indexed tags used to discover relays [`d`] | +| [30066](#k30066) | Relay Metadata | A PRE composed of human readable, non-indexed tags used to find data on a relay [`d`] | -## Table of Contents -- `10066` [Self-reported Relay Meta](#k10066) -- `30066` [Monitor Relay Meta & Status](#k30066) -- `10166` [Monitor Meta Data](#k10166) -- `1066` [Historical Relay Meta](#k1066) +## High Level +nostr is a network composed of dumb relays that exhibit different behaviors that are mostly, but not entirely self-reported by their NIP-11 document. However, discoverabililty of relays, and acquiring metadata for relays at the protocol level is not presently implemented. Additionally, self-reported data has an extremely low cieling and is not always reliable. -## `10066`: "Self-Reported Relay Meta" +## 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 discoverability and parse cases. + + +## Status +Starting in `NIP-66@draft6` **Relay Metadata** and **Relay Discoverability** are considered as two different cases and are split into two different events. However, there remains a pattern for monitors to flag that their `30066` events are indexable. + +## 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 Registration" Events + +### Summary +`10166` is a replacable event herein referred to as "Relay Monitor Registration" 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. + + +### Kind Usage +`NIP-66` kinds can be used by both "Relay Operators" and "Relay Monitors," with the exception that "Relay Operators" **SHOULD NOT** use `10166` + +| Kind | Monitors | Operators | +|-------|----------|-----------| +| `10166` | x | | +| `30066` | x | x | +| `30166` | x | x | + +### Schema + +#### Summary + +#### Non-Indexed Tags + +- `url` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's `website` member in their `kind: 0` JSON for the pubkey that signed the `10066` event. + +- `timeout` The timeout values for various tests. Index `1` is the monitor's timeout in milliseconds. Index `2` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no index `2` is provided, it is inferred that the timeout provided applies to all tests. + ```json + [ "timeout", "open", "2000" ], + [ "timeout", "read", "2000" ], + [ "timeout", "write", "3000" ], + [ "timeout", "nip11", "2000" ], + [ "timeout", "ssl", "4000" ] + ``` + +- `frequency` The frequency at which the monitor publishes events. A string-integer at index `1` represents the frequency **in seconds** of the checks. There should only be `1` frequency per monitor. + + ```json + [ "frequency", "3600" ] + ``` + +#### Indexed Tags +- `k` "Kinds" **should** be a the string-representation of an integer that describes the NIP-66 kinds this monitor publishes. _Note: Kind `10166` **does not** need to be listed here._ + ```json + [ "k", "30066" ], + [ "k", "30166" ] + ``` + + While `30066` and `30166` have a high-level separation of concerns by Metadata and Discoverability, a monitor can decide to flag `30066` as indexable, and include indexed tags defined in `30166` within their `30066` Relay Metadata events. + + ```json + [ "k", "30066", "indexed"], + ``` + +- `c` "Checks" **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `rtt`, `nip11`, `ssl`, `dns`, `geo` and `count`. Other checks can be added via consensus. + + ```json + [ "c", "rtt" ], + [ "c", "nip11" ], + [ "c", "dns" ], + [ "c", "geo" ], + [ "c", "dns" ], + [ "c", "count" ] + ``` + +- `n` "Counts" **should** be a lower-snake-case string describing the counts(s) conducted by a monitor at index `1`. Some examples are: `total_active_users`, `total_note_zaps`, `total_note_reactions`, `events_per_minute`, `note_publish_rate`. Counts are not atomized, their values are entirely ad-hoc. The time period of the count is defined in `30066` + + ```json + [ "n", "users_total_active" ], + [ "n", "note_total_zaps" ], + [ "n", "note_total_reactions" ], + [ "n", "note_publish_rate" ] + ``` + +- `o` The hex pubkey of the owner of the monitor. A "Monitor Service" will likely run several monitors. + ```json + [ "o", "b3b0d247f66bf40c4c9f4ce721abfe1fd3b7529fbc1ea5e64d5f0f8df3a4b6e6" ] + ``` + +- `g`: `NIP-66` leverages a draft NIP for geo tags, which is backwards compatible with `0` collisions for legacy `g` tags from `NIP-52`. See [YAGT](https://github.com/nostr-protocol/nips/pull/952) + ```json + [ "G", "countryCode" ] + [ "g", "US", "countryCode"] + [ "g", "USA", "countryCode" ] + [ "G", "regionCode" ] + [ "g", "US-CA", "regionCode"] + [ "g", "9r1652whz" ] + [ "g", "9r1652wh" ] + [ "g", "9r1652w" ] + [ "g", "9r1652" ] + [ "g", "9r165" ] + [ "g", "9r16" ] + [ "g", "9r1" ] + [ "g", "9r" ] + [ "g", "9" ] + ``` + + +### 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. + +### Example +```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" ], + [ "c", "count" ], + + [ "n", "total_active_users" ], + [ "n", "total_note_zaps" ], + [ "n", "total_note_reactions" ], + [ "n", "events_per_minute" ], + + [ "k", "30066" ], + [ "k", "30166" ], + + ["g", "ww8p1r4t8"], + ["G", "countryCode"], + ["g", "NL", "countryCode"] + ] +} +``` + +## `30166`: "Relay Discoverability" + +### Summary +`30166` is a `NIP-33` Parameterized-Replaceable Event [PRE], referred to as a "Relay Discoverability" event. These events are optimized with a small footprint for protocol-level relay discoverability, and contain no unindexed tags. + +### Purpose +Enables protocol-level discovery of relays on a variety of parameters while ommitting the large footprint of metadata in the "Discovery Case" + +### Schema + +#### Summary +`30166` events contain only indexable tags. + +#### Indexed Tags +- `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://history.nostr.watch/"] + ``` + +- `n`: Network + ```json + [ "n", "clearnet" ] + ``` + +- `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 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 auth + ``` + +- `l`: "Language Tags" _From NIP-11 "Informational Document" `nip11.language_tags[]`_ + ```json + [ "l", "en" ], + [ "l", "en-419" ] + ``` + +- `t`: "Tags" _From NIP-11 "Informational Document" `nip11.tags[]`_ + ```json + [ "t", "nsfw" ] + ``` + +- `k`: Accepted Kinds (Only possible with self-reporting until `accepted` and `rejected` kinds are added to NIP-11) + ```json + [ "k", "0" ], + [ "k", "3" ], + [ "k", "10002" ] + ``` + +- `g`: `NIP-66` leverages a draft NIP for geo tags, which is backwards compatible with `0` collisions for legacy `g` tags from `NIP-52`. See [YAGT](https://github.com/nostr-protocol/nips/pull/952) + ```json + [ "G", "countryCode" ], + [ "g", "US", "countryCode"], + [ "g", "USA", "countryCode" ], + [ "G", "regionCode" ], + [ "g", "US-CA", "regionCode"], + [ "g", "9r1652whz" ], + [ "g", "9r1652wh" ], + [ "g", "9r1652w" ], + [ "g", "9r1652" ], + [ "g", "9r165" ], + [ "g", "9r16" ], + [ "g", "9r1" ], + [ "g", "9r" ], + [ "g", "9" ] + ``` + +#### Required Tags +In order for discoverability to work as intended, please review the following table. + +| tag | should be set | notes | +|-----|----------|--------------------------------------------------------------------------------------------------| +| `d` | yes | NIP-33 | +| `R` | yes | Required so that public and no-auth relays are discoverable | +| `n` | no | | +| `N` | no | | +| `l` | no | | +| `t` | no | | +`o` | no | | +| `k` | no | | + +#### Example +_Relay was online, and you can find it using a bunch of different indexable tags_ +```json +{ + "id": "", + "pubkey": "", + "created_at": "", + "signature": "", + "content": "{}", + "kind": 30166, + "tags": [ + ["d","wss://some.relay/"], + ["n", "clearnet"], + ["N", "7"], + ["N", "33"], + ["k", "0" ], + ["k", "3" ], + ["k", "10002" ], + ["R", "!payment"], + ["R", "!auth"], + ["l", "en"], + ["l", "es"], + ["l", "fr"], + ["g", "ww8p1r4t8"], + ["G", "countryCode"], + ["g", "NL", "countryCode"] + ] +} +``` + +#### Tag availability mapping +When a monitor flags check support [`c` tag] in their `10166` kind, related indexable fields **SHOULD** be present in their published `30166` event kinds. + +| check | indexable tags | +|-------|-----------------| +| rtt | n/a | +| nip11 | `N` `R` `l` `t` | +| ssl | n/a | +| dns | n/a | +| geo | n/a | + +##### Important Notes +- Relay Monitors that publish `30166` events **SHOULD** at a minimum be conducting `rtt` checks, namely websocket `open`, so that clients can determine liveness. +- `k` indexable tags are not associated to any other standard and thus cannot be flagged for support in `10166` until `NIP-11` support kind flagging. + +## `30066`: "Relay Metadata" ### Summary -An event that contains data about a relay. These events are self-reported by relays from the `owner` pubkey defined in their Information Document (`NIP-11`). Hereinafter referred to as "Relay Meta" events +`30066` is a `NIP-33` Parameterized-Replaceable Event [PRE], referred to as a "Relay Metadata" event. These events store the existence and optionally some data relating to the relay. These events can be published by a monitor or self published by relay operators -### Purpose -An event published by a relay owner that makes the owner's relay discoverable. +### Purpose +To store useful, computationally expensive data derived from checks and other metadata about relays. This data is found by filtering the normalized relay URL with the `d` tag. Determining liveness `30066` can be used by filtering against `since` with respect to the `frequency` value set in a **Relay Monitor's** `10166` event kind. ### Schema #### `event.content` -**Should** be empty. +`content` **MAY** contain stringified `NIP-11` JSON, since the `NIP-11` cannot be serialized into tags with any sane patterns. #### `event.tags` -"Self-Reported Relay Meta" events have **one** (1) required tag. -"Self-Reported Relay Meta" events have **two** (2) non-standard, NIP-66 specific indexable tags. - -Tags should be used to represent the Relay's abilities and meta at any given point in time. The "tags schema" is expressed using pseudo-types for reasons of communication and brevity, for example `tagDescriptor[]`. This NIP utilizes `NIP-32` to expose indexable values. +##### Summary +1. "Relay Metadata" events have **one** (1) required tag +2. **Unindexed Tags** use grouping by defining the _group_ at index position `1`, the key at index position `2` and the value at index position `3`. -#### Tags -- `"r" == tagId[0]` The relay URL. The `#d` tag **must** be included in the `event.tags[]` array. `tagId[1]` **must** be the relay websocket URL. The URL **should** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) +#### Indexed Tags +- `d` The relay URL. The `#d` tag **MUST** be included in the `event.tags[]` array. Index position `1` **SHOULD** be the relay websocket URL. The URL **SHOULD** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) + ```json + [ "d", "wss://history.nostr.watch/"] ``` - ["d", "wss://history.nostr.watch/"] //tagId[] +- `30066` events **MAY** contain any of the indexable tags included in `30166` kind events (See instructions for this case in `10166`'s schema, specifically under `k`) +#### Unindexed Tags +- `rtt` group contains key/value pairs that describe the round trip time of a particular operation. Values at position `2...` **SHOULD** treated as an array by consumers. This array can be used to **mathematically** find `min`, `max`, `average` and `median` values. For example `Math.min(...["190", "201", "540"].map( n => parseInt(n) ))`. Some obvious index `1` keys are websocket `open`, `read` and `write` round-trip times, as well as `nip11` https request round-trip time. + ```json + ["rtt", "open", "190", "201", "540"], + ["rtt", "read", "35"], + ["rtt", "write", "701"] ``` -- `n`: Such as `clearnet`, `tor`, `i2p`, `cjdns`, etc _in the context of **NIP-66 only**_ - ``` - [ "n", "clearnet" ] +- `ssl` group contains key/value pairs that describe the checked status of a relay's SSL Certificate. Index `1` keys for `ssl` can be atomized and should be one of the following `valid_from`, `valid_to`, `subject_alt_name`, `fingerprint`, `fingerprint256`, `fingerprint512`, `ext_key_usage`, `exponent`, `serial_number`, `modulus` and/or `pem_encoded`. There **SHOULD NOT** be duplicate keys. + ```json + ["ssl", "valid_from", ""], + ["ssl", "valid_to", ""] ``` -- `desc == tagDesc[0]` The `description` from relay's NIP-11 information document. - ``` - [ "desc", "A nostr relay" ] +- `dns` group contains key/value pairs that describe a DNS lookup for the relay from the perspective of a given monitor. It can provide insights on other meta data in the event. Index `1` keys for `dns` can be atomized and should be one of the following `as`, `asn`, `ipv4` or `ipv6`. There **MAY** be duplicate keys. + ```json + ["dns", "asn", "19281"], + ["dns", "as", "QUAD9-AS-1, CH"], + ["dns", "ipv4", "1.1.1.1"], + ["dns", "ipv6", "2001:db8:3333:4444:5555:6666:7777:8888"] ``` -- `name == tagname[0]` The `name` member from relay's NIP-11 information document. +- `nip11` group is a special group that extracts specific values as long as they are no more than 1 level deep and do not contain arrays of objects. This data **MAY** be duplicated as stringified `NIP-11` JSON in content. + ```json + ["nip11", "name", "A nostr relay"], + ["nip11", "description", "It stores notes and other stuff"], + ["nip11", "owner", ""], + ["nip11", "software", ""], + ["nip11", "version", ""] ``` - [ "desc", "A nostr relay" ] + For arrays + ```json + ["nip11", "supported_nips", "3", "33"], ``` -- `N`: Supported NIPs _in the context of **NIP-66 only**_ - ``` - [ "N", "1" ] - [ "N", "11" ] - [ "N", "33" ] +- `count` Meta values for arbitrary counts related to a relay. Index position `1` is the value expressed as the string representation of an integer or float. Index position `2` is the key and describes the count, such as `total_users` or `total_events`. Index position `3` **MAY** be set and defines the "period" in seconds that the count at position `2` was calculated. Counts **SHOULD** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. A count's key **SHOULD** be **snake case**. There **MAY** be zero (0) to many count tags. + + ```json + ["count", "users_total_active", "201", "86400"], + ["count", "note_total_zaps", "87", "86400"], + ["count", "note_total_reactions", "125", "86400"], + ["count", "note_publish_rate", "24.1", "3600"] ``` -- `"count" == tagCount[0]` Meta values for arbitrary counts related to a relay. `tagCount[1]` is the value expressed as the string representation of an integer or float. `tagCount[2]` is the key and describes the count, such as `total_users` or `total_events`. Counts **should** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. A count's key should be **snake case**. There **may** be zero (0) to many count tags. - - ``` - ["count", "502341", "total_events"], - ["count", "52000", "total_users"], - ["count", "321", "active_users_24h"] - ["count", "21.4", "events_per_minute"] +- `other`: A group for other type checks that could be a derivative of another check or unassociated to a specific check. A good example is `network` which is is determined by parsing the URL to attempt to identify which network it can be found on, and would likely already be in the monitor's cache as it was determined for discoverability purposes. + ```json + ["other", "network", "clearnet"] ``` -- `"infohash" == tagInfohash[0]` A SHA256 hash of the deterministically stringified `NIP-11` "Info Document" JSON at `tagInfohash[1]` - ``` - [ "infohash", "8332f76d1fbbd3c83abc8eeb5cac296fb7514b9b06d8734f98c16c246d6ec590" ] - ``` +#### Tag Usage +For self-reported `30066` events by "Relay Operators", certain tags **SHOULD NOT** be self-published or otherwised ignored by clients if present. Please reference the table below. -#### Label Tags NIP-32 -- `relay_type`, for example `proxy`, `bridge` and `public`. There **may** be more than one type. _Please note,_ at time of writing there has been no collective effort to atomize relay types, so these values cannot be enumerated. - ``` - [ "L", "relay_type" ] - [ "l", "proxy", "relay_type" ] - [ "l", "public", "relay_type" ] - ``` - -- `ipv4`/`ipv6`, relay ips. - ``` - [ "L", "ipv4" ] - [ "l", "1.1.1.1", "ipv4" ] - [ "L", "ipv6" ] - [ "l", "2001:db8:3333:4444:5555:6666:7777:8888"", "ipv6" ] - ``` - -- `as`/`asn` the relay ISPs "Autonomous System (Number)" - ``` - [ "L", "as" ] - [ "l", "QUAD9-AS-1, CH", "as" ] - [ "L", "asn" ] - [ "l", "19281", "asn" ] - ``` - -- String values from `NIP-11` using dot notation, for example - ``` - [ "L", "nip11.tags" ] - [ "l", "sfw-only", "nip11.tags" ] - [ "l", "bitcoin-only", "nip11.tags" ] - [ "L", "nip11.language_tags" ] - [ "l", "en", "nip11.language_tags" ] - [ "l", "en-419", "nip11.language_tags" ] - ``` - -- Boolean values from `NIP-11`, for example - ``` - [ "L", "nip11.limitation" ] - [ "l", "payment_required", "nip11.limitation" ] //nip11.limitation payment_required==true - [ "l", "auth_required", "nip11.limitation" ] //nip11.limitation auth_required==true - ``` - -#### NIP-11 Integer Values -Any NIP-11 values that are integers **should not** be included as NIP-32 labels, instead NIP-11 integer vlaues should use the `nip11` tag. - -``` -[ "nip11", "65535", "limitation.max_message_length" ] -``` - -#### NIP-11 Nested Objects -NIP-11 nested objects are not supported by NIP-66 at this time (For example, fees) - -#### Geo tags NIP-YAGT -- `NIP-66` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) - ``` - [ 'G', 'countryCode' ] - [ 'g', 'US', 'countryCode'] - [ 'g', 'USA', 'countryCode' ] - [ 'g', '840', 'countryCode' ] - [ 'G', 'regionCode' ] - [ 'g', 'US-CA', 'regionCode'] - [ 'g', '9r1652whz' ] - [ 'g', '9r1652wh' ] - [ 'g', '9r1652w' ] - [ 'g', '9r1652' ] - [ 'g', '9r165' ] - [ 'g', '9r16' ] - [ 'g', '9r1' ] - [ 'g', '9r' ] - [ 'g', '9' ] - ``` - -#### Topic Tags -- `NIP-66` leverages topics [`t` tags] and optionally adds values at positions `tag[2]` and `tag[3]`. If `tag[2]` is set, it **should** be a string-integer representing the number of tags on the relay. If `tag[2]` is set, `tag[3]` **should** be set and be a string-integer representing the timeframe **in seconds** for the value set as `tag[2]`. This tag is used to indicate topics relevant to the relay through event analysis (as oppossed to 'tags' from `NIP-11` document) - - ``` - ["t", "meme", "69", "3600"] - ``` - -## `30066`: "Relay Status" Events - -### Summary -`30066` is a parameterized replaceable event [NIP-33], referred to as a "Relay Status" event. These events store the existence and optionally some data relating to the relay. - -### Purpose -To store useful, computationally expensive relay meta-data about relays. `30066` should be used to give a canonical reference to the last known functional state of a relay, to be evaluated subjectively by a client and/or user to derive conclusions from. - -### NIPs Used -- `NIP-32` Labels -- `NIP-33` Parameterized Replacable Events -- `NIP-40` Expirable Events -- [YAGT](https://github.com/nostr-protocol/nips/pull/952) _draft_ - -### Schema -`30066` inherit the schema from `10066`, with a substitution and some additional tags. - -_**Different referencial tag**_ - -- `30066` uses a `d` tag instead of an `r` tag for the normalized relay URL since it is a Parameterized-Replaceable Event - -_**It adds some additional tags**_ - -- `"rtt" == tagRtt[0]` Round-trip time of websocket ping/pong in milliseconds. Example values for `tagRtt[1]` are `open`, `read` and `write`. Where `open` represents the round-trip time forWebsocket to open, `read` represents the round-trip time of a Websocket `REQ` (subscription) message's response, and `write` represents the round-trip time of a Websocket `EVENT` (publish) message and subsequent `ok` message. `tagRtt[2...]` are strings with the millisecond values. At a minimum `tagRtt[2]` **should** be set. When more than one value is provided, values **may** be treated as an array to find `min`, `max`, `average` and `median` values. There **may** be zero `rtt` tags. - - ``` - ["rtt", "open", "201", "190", "540"], - ["rtt", "read", "35", "60", "46"], - ["rtt", "write", "701", "497", "508"] - ``` +| | Monitor | Relay Operators | +|----------|---------|-----------------| +| rtt | x | | +| nip11 | x | x | +| dns | x | x | +| geo | x | x | +| ssl | x | | +| count | x | x | +| other | x | x | #### Methodology -A Relay Monitor publishes `30066`` events exclusively when a relay is operational. This approach ensures that the last known active state of the relay is maintained and recorded. Based on this data, several inferences can be drawn about the relay's status and characteristics +A _Relay Monitor_ publishes `30066` events exclusively when a relay is reachable. This approach ensures that the last known active state of the relay is maintained and recorded in `created_at` value of event. Based on this data, several inferences can be drawn about the relay's status and characteristics. 1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events using `since`. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online. 2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. The are responsible for setting and applying arbitrary thresholds using `until` filters or post-processing to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor. -3. For relay status events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics and performance, which might not be currently accessible due to the relay being offline. +3. For [Relay Metadata](#k30066) events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics, performance and impact on the network, which might not be currently accessible due to the relay being offline. #### Important Notes -- `NIP-11` values are provided as means to filter and discover relays, however **should not** be used as a replacement to `NIP-11`. -- A particular relay's retention policy could conflict with subjective thresholds used in determination of "online" or "dead" relays and so care should be taken with regards to chosen relays by both monitors and consumers. +- Relay Monitors **SHOULD** run checks and publish events according to the `frequency` value set in their respective `10166` kind event. +- If a relay monitor publishes both `30166` and `30066` kind events, they **SHOULD** publish both on every check. +- Clients **SHOULD** only use monitors reporting `rtt` values for websockets (particularly `open`) for determining the "liveness" or "deadness" of a relay. +- Clients **SHOULD** consider the `frequency` value in a monitor's `10166` when trying to reach determination of "liveness". +- `NIP-11` values are provided as means to filter and discover relays, however ****SHOULD NOT** be used as a replacement to `NIP-11`. +- A particular relay's retention policy could conflict with subjective thresholds used in determination of "liveness" or "deadness" of relays and so care **SHOULD** be taken with regards to chosen relays for `NIP-66` by both monitors and consumers. #### Examples -##### Minimum Requirements, "Relay was online at `Date(created_at)`" +##### Minimum Requirements +_"Relay was online at ``"_ ```json { "id": "", @@ -211,53 +432,53 @@ A Relay Monitor publishes `30066`` events exclusively when a relay is operationa } ``` -##### Relay is checked and online example, "Relay is online and here's some meta-data this monitor believes is accurate" +##### Relay is checked and online +_"Relay was online at and here's some meta-data this monitor believes is accurate"_ ```json { "id": "", "pubkey": "", - "created_at": "", + "created_at": "", "signature": "", - "content": "{}", + "content": "{\"contact\":\"pablof7z.com\",\"description\":\"Nostr's Purple Pages\",\"name\":\"purplepag.es\",\"pubkey\":\"fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52\",\"software\":\"git+https://github.com/hoytech/strfry.git\",\"supported_nips\":[1,2,4,9,11,12,16,20,22,28,33,40],\"version\":\"0.9.6-7-g7196547\"}", "kind": 30066, "tags": [ ["d","wss://some.relay/"], - ["n", "clearnet"] - ["N", "1"], - ["N", "7"], - ["rtt", "open", "201", "190", "540"], - ["rtt", "read", "35", "60", "46"], - ["rtt", "write", "701", "497", "508"], - ["ssl", "valid", "timestamp", "timestamp"], - ["count", "21.4", "events_per_minute"], - ["g", "ww8p1r4t8"], - ["G", "countryCode"] - ["g", "NL", "countryCode"], - ["L", "ipv4"], - ["l", "1.1.1.1", "ipv4" ], - ["L", "ipv6"], - ["l", "2001:db8:3333:4444:5555:6666:7777:8888", "ipv6"], - ["L", "nip11.tags" ], - ["l", "sfw-only", "nip11.tags" ], - ["l", "bitcoin-only", "nip11.tags" ] - ["L", "nip11.language_tags" ], - ["l", "en", "nip11.language_tags" ], - ["l", "en-419", "nip11.language_tags" ], - ["nip11", "65535", "limitation.max_message_length" ] + ["other", "network", "clearnet"] + ["rtt", "open", "190", "201", "540"], + ["rtt", "read", "35"], + ["rtt", "write", "701"], + ["nip11", "name", "A nostr relay"], + ["nip11", "description", "It stores notes and other stuff"], + ["nip11", "owner", ""], + ["nip11", "software", ""], + ["nip11", "version", ""], + ["ssl", "valid_from", ""], + ["ssl", "valid_to", ""], + ["geo", "geohash", "ww8p1r4t8"], + ["geo", "countryCode", "NL"], + ["dns", "asn", "19281"], + ["dns", "as", "QUAD9-AS-1, CH"], + ["dns", "ipv4", "1.1.1.1"], + ["dns", "ipv6", "2001:db8:3333:4444:5555:6666:7777:8888"], + ["count", "users_total_active", "201", "86400"], + ["count", "note_total_zaps", "87", "86400"], + ["count", "note_total_reactions", "125", "86400"], + ["count", "note_publish_rate", "24.1", "3600"] ] } ``` #### Testing Criteria -The testing criteria to determine conditions defined in event's tags **may** be subjective and **may** vary between monitors. +The testing criteria to determine conditions defined in event's tags **MAY** be subjective and **MAY** vary between monitors. #### Limitations -The data in `30066` **may** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **should** be subscribed to by populating the `authors` filter array with the poublic keys of trusted **monitors** and where security or privacy is a concern any republished values (such as NIP-11 values) should instead be attained from the source. All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. +The data in `30066` **MAY** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **SHOULD** be subscribed to by populating the `authors` filter array with the public keys of subjectively **trusted monitors** and where security or privacy is a concern any republished values (such as NIP-11 values) should instead be attained from the source (https). All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. -#### Ammending NIP-66 +## Ammending NIP-66 Any test results that cannot be expressed through `NIP-66` **should** be ammended to the nip following discussion and general consensus -### Use Cases +## 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 Improvement Proposals (NIPs), ensuring compatibility with desired protocol features. @@ -276,109 +497,4 @@ Any test results that cannot be expressed through `NIP-66` **should** be ammende 9. **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. -10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. - -## `10166`: "Relay Monitor" Events - -### Summary -`10166` is a replacable event herein referred to as "Relay Monitor" events. These events contain information about a publisher's intent to monitor and/or aggregate relays and publish data as `30066` events. - -### Purpose -To provide a directory of monitors, their intent to publish, their criteria and parameters of monitoring activities. - -### Schema -`10166` events have no required tags. - -- `"url" == tagUrl[0]` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's kind 0 for the pubkey that signed the `10066` event. - -- `"timeout" == tagTimeout[0]` The timeout values for various tests. `tagTimeout[1]` is the monitor's timeout in milliseconds. `tagTimeout[2]` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no `tagTimeout[2]` is provided, it is inferred that the timeout provided applies to all tests. - ``` - [ "timeout", "2000", "open" ] - [ "timeout", "2000", "read" ] - [ "timeout", "3000", "write" ] - [ "timeout", "2000", "nip11" ] - ``` - -- `"kind === tagKind[0]"` The kind(s) this monitor publishes. - ``` - [ "kind", "30066" ] - [ "kind", "1066" ] - ``` - -- `"frequency" == tagFrequency[0]` The frequency at which the monitor publishes events. A string-integer at `tagFrequency[1]` represents the frequency **in seconds** a event kind is published. The string-integer at `tagFrequency[2]` represents the kind bound to the frequency. If `tagFrequency[2]` is undefined, it is inferred the timeout applies to all events published by the monitor. A frequency **should not** be created for this kind [`1006`]. If a kind is referenced in `tagFrequency` that is not set in `tagKind` it should be disregarded. - ``` - [ "frequency", "3600", "30066" ] - [ "frequency", "3600", "1066" ] - ``` - -#### Label Tags NIP-32 - -- `checks` **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `websocket`, `nip11`, `ssl`, `dns`, `geo` - - ``` - [ "L", "checks" ] - [ "l", "websocket", "checks" ] - [ "l", "nip11", "checks" ] - [ "l", "ssl", "checks" ] - [ "l", "dns", "checks" ] - [ "l", "geo", "checks" ] - ``` - -#### Geo tags NIP-YAGT -- Kind `10166` leverages a draft NIP for geo tags, see [YAGT](https://github.com/nostr-protocol/nips/pull/952) - -### 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. - -### Example -```json -{ - "id": "", - "pubkey": "", - "created_at": "", - "signature": "", - "content": "{}", - "tags": [ - [ "url", "wss://bob.some.guy"], - - [ "L", "checks" ], - [ "l", "websocket", "checks" ], - [ "l", "nip11", "checks" ], - - [ "kind", "30066" ], - [ "kind", "1066" ], - - [ "frequency", "3600", "30066" ], - [ "frequency", "3600", "1066" ], - - [ "timeout", "5000", "open" ], - [ "timeout", "3000", "read" ], - [ "timeout", "3000", "write" ], - [ "timeout", "2000", "nip11" ], - - ["g", "ww8p1r4t8"], - ["G", "countryCode"], - ["g", "NL", "countryCode"] - ] -} -``` - -## `1066`: "Relay Status History" Events - -### Summary -`3066` is a standard nostr event, referred to as a "Relay Status History" event. These events store the history of a relay at the periodic interval defined in the monitor's `10166`. - -#### Schema -Relay History events can contain any of the tags defined for kind `30066`. The `d` tag should be included in every `3066` event, as it can be used to filter historical events by relay URL. - -#### Special Considerations -- These events can potentially demand a lot of disk space if not used wisely. - -#### Guidelines -Tags representing less-volatile values, for instance `nip11.software` vs `rtt`, contained with this event should only be included when their respectiive values have changed compared to the last Relay History event of the same `d` tag. If there have been no changes, then the event should not be published. - -##### Use Cases -- Generate a time series from one or data-point(s) for a specific relay. -- Generate network-wide aggregated statistics \ No newline at end of file +10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. \ No newline at end of file From ceabeccb8884f61541c2baf7b903018a99299c85 Mon Sep 17 00:00:00 2001 From: Sandwich <299465+dskvr@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:37:08 +0200 Subject: [PATCH 30/34] draft7 --- 66.md | 458 ++++++++++++++-------------------------------------------- 1 file changed, 111 insertions(+), 347 deletions(-) diff --git a/66.md b/66.md index 5893bddc..2add0f28 100644 --- a/66.md +++ b/66.md @@ -1,29 +1,36 @@ -# NIP-66: Relay Meta and Monitoring System +# NIP-66: Relay Discovery and Liveness Monitoring `draft` `optional` -## Table of Kinds -This NIP defines three (3) event kinds, `30066`, `30166` and `10166` +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 Registration | An RE that stores data to publish intent to monitor and details around their activities | -| [30166](#k30166) | Relay Discoverability | A PRE composed of only indexed tags used to discover relays [`d`] | -| [30066](#k30066) | Relay Metadata | A PRE composed of human readable, non-indexed tags used to find data on a relay [`d`] | - -## High Level -nostr is a network composed of dumb relays that exhibit different behaviors that are mostly, but not entirely self-reported by their NIP-11 document. However, discoverabililty of relays, and acquiring metadata for relays at the protocol level is not presently implemented. Additionally, self-reported data has an extremely low cieling and is not always reliable. - -## 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 discoverability and parse cases. - - -## Status -Starting in `NIP-66@draft6` **Relay Metadata** and **Relay Discoverability** are considered as two different cases and are split into two different events. However, there remains a pattern for monitors to flag that their `30066` events are indexable. +| [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 @@ -31,110 +38,56 @@ Starting in `NIP-66@draft6` **Relay Metadata** and **Relay Discoverability** are - `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 Registration" Events +## `10166`: "Relay Monitor Announcement" Events ### Summary -`10166` is a replacable event herein referred to as "Relay Monitor Registration" events. These events contain information about a publisher's intent to monitor and publish data as `NIP-66` events. +`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. - - -### Kind Usage -`NIP-66` kinds can be used by both "Relay Operators" and "Relay Monitors," with the exception that "Relay Operators" **SHOULD NOT** use `10166` - -| Kind | Monitors | Operators | -|-------|----------|-----------| -| `10166` | x | | -| `30066` | x | x | -| `30166` | x | x | +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 -#### Summary - #### Non-Indexed Tags -- `url` A URL with human readable information about the monitor's activities. If not included, it is assumed these details are included in the monitor's `website` member in their `kind: 0` JSON for the pubkey that signed the `10066` event. - -- `timeout` The timeout values for various tests. Index `1` is the monitor's timeout in milliseconds. Index `2` describes what test the timeout is used for, for example `open`, `read`, `write`, `info`, etc. If no index `2` is provided, it is inferred that the timeout provided applies to all tests. - ```json - [ "timeout", "open", "2000" ], - [ "timeout", "read", "2000" ], - [ "timeout", "write", "3000" ], - [ "timeout", "nip11", "2000" ], - [ "timeout", "ssl", "4000" ] - ``` - -- `frequency` The frequency at which the monitor publishes events. A string-integer at index `1` represents the frequency **in seconds** of the checks. There should only be `1` frequency per monitor. +- `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 -- `k` "Kinds" **should** be a the string-representation of an integer that describes the NIP-66 kinds this monitor publishes. _Note: Kind `10166` **does not** need to be listed here._ +- `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 - [ "k", "30066" ], - [ "k", "30166" ] - ``` - - While `30066` and `30166` have a high-level separation of concerns by Metadata and Discoverability, a monitor can decide to flag `30066` as indexable, and include indexed tags defined in `30166` within their `30066` Relay Metadata events. - - ```json - [ "k", "30066", "indexed"], - ``` - -- `c` "Checks" **should** be a lowercase string describing the check(s) conducted by a monitor. Some examples are: `rtt`, `nip11`, `ssl`, `dns`, `geo` and `count`. Other checks can be added via consensus. - - ```json - [ "c", "rtt" ], + [ "c", "ws" ], [ "c", "nip11" ], [ "c", "dns" ], [ "c", "geo" ], - [ "c", "dns" ], - [ "c", "count" ] + [ "c", "ssl" ], ``` -- `n` "Counts" **should** be a lower-snake-case string describing the counts(s) conducted by a monitor at index `1`. Some examples are: `total_active_users`, `total_note_zaps`, `total_note_reactions`, `events_per_minute`, `note_publish_rate`. Counts are not atomized, their values are entirely ad-hoc. The time period of the count is defined in `30066` - +- `g`: `NIP-52` `g` tags (geohash) ```json - [ "n", "users_total_active" ], - [ "n", "note_total_zaps" ], - [ "n", "note_total_reactions" ], - [ "n", "note_publish_rate" ] - ``` - -- `o` The hex pubkey of the owner of the monitor. A "Monitor Service" will likely run several monitors. - ```json - [ "o", "b3b0d247f66bf40c4c9f4ce721abfe1fd3b7529fbc1ea5e64d5f0f8df3a4b6e6" ] - ``` - -- `g`: `NIP-66` leverages a draft NIP for geo tags, which is backwards compatible with `0` collisions for legacy `g` tags from `NIP-52`. See [YAGT](https://github.com/nostr-protocol/nips/pull/952) - ```json - [ "G", "countryCode" ] - [ "g", "US", "countryCode"] - [ "g", "USA", "countryCode" ] - [ "G", "regionCode" ] - [ "g", "US-CA", "regionCode"] [ "g", "9r1652whz" ] - [ "g", "9r1652wh" ] - [ "g", "9r1652w" ] - [ "g", "9r1652" ] - [ "g", "9r165" ] - [ "g", "9r16" ] - [ "g", "9r1" ] - [ "g", "9r" ] - [ "g", "9" ] ``` +- Any other globally defined indexable tags **MAY** be included as found necessary. ### Other Requirements -Monitors **should** have the following +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. -### Example +### Robust Example of a `10166` Event ```json { "id": "", @@ -143,7 +96,7 @@ Monitors **should** have the following "signature": "", "content": "", "tags": [ - [ "url", "https://a.good.monitor"], + [ "url", "https://a.good.monitor/"], [ "timeout", "open", "5000" ], [ "timeout", "read", "3000" ], @@ -156,41 +109,42 @@ Monitors **should** have the following [ "c", "nip11" ], [ "c", "ssl" ], [ "c", "dns" ], - [ "c", "geo" ], - [ "c", "count" ], + [ "c", "geo" ] - [ "n", "total_active_users" ], - [ "n", "total_note_zaps" ], - [ "n", "total_note_reactions" ], - [ "n", "events_per_minute" ], - - [ "k", "30066" ], - [ "k", "30166" ], - - ["g", "ww8p1r4t8"], - ["G", "countryCode"], - ["g", "NL", "countryCode"] + [ "g", "ww8p1r4t8" ] ] } ``` -## `30166`: "Relay Discoverability" +## `30166`: "Relay Discovery" ### Summary -`30166` is a `NIP-33` Parameterized-Replaceable Event [PRE], referred to as a "Relay Discoverability" event. These events are optimized with a small footprint for protocol-level relay discoverability, and contain no unindexed tags. +`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 protocol-level discovery of relays on a variety of parameters while ommitting the large footprint of metadata in the "Discovery Case" +Enables the discovery of relays via nostr protocol. ### Schema -#### Summary -`30166` events contain only indexable tags. +#### 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. -#### Indexed Tags +#### `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://history.nostr.watch/"] + [ "d", "wss://somerelay.abc/"] ``` - `n`: Network @@ -198,6 +152,11 @@ Enables protocol-level discovery of relays on a variety of parameters while ommi [ "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" ] @@ -208,65 +167,34 @@ Enables protocol-level discovery of relays on a variety of parameters while ommi [ "R", "payment" ], [ "R", "auth" ], ``` - Since 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 + 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 auth + [ "R", "!auth" ], //no authentication required ``` -- `l`: "Language Tags" _From NIP-11 "Informational Document" `nip11.language_tags[]`_ - ```json - [ "l", "en" ], - [ "l", "en-419" ] - ``` - -- `t`: "Tags" _From NIP-11 "Informational Document" `nip11.tags[]`_ +- `t`: "Topics" _From NIP-11 "Informational Document" `nip11.tags[]`_ ```json [ "t", "nsfw" ] ``` -- `k`: Accepted Kinds (Only possible with self-reporting until `accepted` and `rejected` kinds are added to NIP-11) +- `k`: Accepted Kinds ```json [ "k", "0" ], [ "k", "3" ], [ "k", "10002" ] ``` -- `g`: `NIP-66` leverages a draft NIP for geo tags, which is backwards compatible with `0` collisions for legacy `g` tags from `NIP-52`. See [YAGT](https://github.com/nostr-protocol/nips/pull/952) +- `g`: `NIP-52` `g` tags (geohash) ```json - [ "G", "countryCode" ], - [ "g", "US", "countryCode"], - [ "g", "USA", "countryCode" ], - [ "G", "regionCode" ], - [ "g", "US-CA", "regionCode"], - [ "g", "9r1652whz" ], - [ "g", "9r1652wh" ], - [ "g", "9r1652w" ], - [ "g", "9r1652" ], - [ "g", "9r165" ], - [ "g", "9r16" ], - [ "g", "9r1" ], - [ "g", "9r" ], - [ "g", "9" ] + [ "g", "9r1652whz" ] ``` -#### Required Tags -In order for discoverability to work as intended, please review the following table. +- `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`. -| tag | should be set | notes | -|-----|----------|--------------------------------------------------------------------------------------------------| -| `d` | yes | NIP-33 | -| `R` | yes | Required so that public and no-auth relays are discoverable | -| `n` | no | | -| `N` | no | | -| `l` | no | | -| `t` | no | | -`o` | no | | -| `k` | no | | - -#### Example -_Relay was online, and you can find it using a bunch of different indexable tags_ +#### Robust Example of a `30166` Event +_Relay was online, and you can filter on a number of different tags_ ```json { "id": "", @@ -278,223 +206,59 @@ _Relay was online, and you can find it using a bunch of different indexable tags "tags": [ ["d","wss://some.relay/"], ["n", "clearnet"], - ["N", "7"], + ["N", "40"], ["N", "33"], - ["k", "0" ], - ["k", "3" ], - ["k", "10002" ], ["R", "!payment"], - ["R", "!auth"], - ["l", "en"], - ["l", "es"], - ["l", "fr"], + ["R", "auth"], ["g", "ww8p1r4t8"], - ["G", "countryCode"], - ["g", "NL", "countryCode"] + ["p", "somehexkey..."], + ["l", "en", "ISO-639-1"], + ["t", "nsfw" ], + ["rtt-open", 234 ] ] } ``` -#### Tag availability mapping -When a monitor flags check support [`c` tag] in their `10166` kind, related indexable fields **SHOULD** be present in their published `30166` event kinds. - -| check | indexable tags | -|-------|-----------------| -| rtt | n/a | -| nip11 | `N` `R` `l` `t` | -| ssl | n/a | -| dns | n/a | -| geo | n/a | - -##### Important Notes -- Relay Monitors that publish `30166` events **SHOULD** at a minimum be conducting `rtt` checks, namely websocket `open`, so that clients can determine liveness. -- `k` indexable tags are not associated to any other standard and thus cannot be flagged for support in `10166` until `NIP-11` support kind flagging. - -## `30066`: "Relay Metadata" - -### Summary -`30066` is a `NIP-33` Parameterized-Replaceable Event [PRE], referred to as a "Relay Metadata" event. These events store the existence and optionally some data relating to the relay. These events can be published by a monitor or self published by relay operators - -### Purpose -To store useful, computationally expensive data derived from checks and other metadata about relays. This data is found by filtering the normalized relay URL with the `d` tag. Determining liveness `30066` can be used by filtering against `since` with respect to the `frequency` value set in a **Relay Monitor's** `10166` event kind. - -### Schema - -#### `event.content` -`content` **MAY** contain stringified `NIP-11` JSON, since the `NIP-11` cannot be serialized into tags with any sane patterns. - -#### `event.tags` - -##### Summary -1. "Relay Metadata" events have **one** (1) required tag -2. **Unindexed Tags** use grouping by defining the _group_ at index position `1`, the key at index position `2` and the value at index position `3`. - -#### Indexed Tags -- `d` The relay URL. The `#d` tag **MUST** be included in the `event.tags[]` array. Index position `1` **SHOULD** be the relay websocket URL. The URL **SHOULD** be [normalized](https://datatracker.ietf.org/doc/html/rfc3986#section-6) - ```json - [ "d", "wss://history.nostr.watch/"] - ``` -- `30066` events **MAY** contain any of the indexable tags included in `30166` kind events (See instructions for this case in `10166`'s schema, specifically under `k`) -#### Unindexed Tags -- `rtt` group contains key/value pairs that describe the round trip time of a particular operation. Values at position `2...` **SHOULD** treated as an array by consumers. This array can be used to **mathematically** find `min`, `max`, `average` and `median` values. For example `Math.min(...["190", "201", "540"].map( n => parseInt(n) ))`. Some obvious index `1` keys are websocket `open`, `read` and `write` round-trip times, as well as `nip11` https request round-trip time. - ```json - ["rtt", "open", "190", "201", "540"], - ["rtt", "read", "35"], - ["rtt", "write", "701"] - ``` - -- `ssl` group contains key/value pairs that describe the checked status of a relay's SSL Certificate. Index `1` keys for `ssl` can be atomized and should be one of the following `valid_from`, `valid_to`, `subject_alt_name`, `fingerprint`, `fingerprint256`, `fingerprint512`, `ext_key_usage`, `exponent`, `serial_number`, `modulus` and/or `pem_encoded`. There **SHOULD NOT** be duplicate keys. - ```json - ["ssl", "valid_from", ""], - ["ssl", "valid_to", ""] - ``` - -- `dns` group contains key/value pairs that describe a DNS lookup for the relay from the perspective of a given monitor. It can provide insights on other meta data in the event. Index `1` keys for `dns` can be atomized and should be one of the following `as`, `asn`, `ipv4` or `ipv6`. There **MAY** be duplicate keys. - ```json - ["dns", "asn", "19281"], - ["dns", "as", "QUAD9-AS-1, CH"], - ["dns", "ipv4", "1.1.1.1"], - ["dns", "ipv6", "2001:db8:3333:4444:5555:6666:7777:8888"] - ``` - -- `nip11` group is a special group that extracts specific values as long as they are no more than 1 level deep and do not contain arrays of objects. This data **MAY** be duplicated as stringified `NIP-11` JSON in content. - ```json - ["nip11", "name", "A nostr relay"], - ["nip11", "description", "It stores notes and other stuff"], - ["nip11", "owner", ""], - ["nip11", "software", ""], - ["nip11", "version", ""] - ``` - For arrays - ```json - ["nip11", "supported_nips", "3", "33"], - ``` - -- `count` Meta values for arbitrary counts related to a relay. Index position `1` is the value expressed as the string representation of an integer or float. Index position `2` is the key and describes the count, such as `total_users` or `total_events`. Index position `3` **MAY** be set and defines the "period" in seconds that the count at position `2` was calculated. Counts **SHOULD** only be included when representing unique or computationally expensive counts, not ones that can be easily achieved via `NIP-45` counts. A count's key **SHOULD** be **snake case**. There **MAY** be zero (0) to many count tags. - - ```json - ["count", "users_total_active", "201", "86400"], - ["count", "note_total_zaps", "87", "86400"], - ["count", "note_total_reactions", "125", "86400"], - ["count", "note_publish_rate", "24.1", "3600"] - ``` - -- `other`: A group for other type checks that could be a derivative of another check or unassociated to a specific check. A good example is `network` which is is determined by parsing the URL to attempt to identify which network it can be found on, and would likely already be in the monitor's cache as it was determined for discoverability purposes. - ```json - ["other", "network", "clearnet"] - ``` - -#### Tag Usage -For self-reported `30066` events by "Relay Operators", certain tags **SHOULD NOT** be self-published or otherwised ignored by clients if present. Please reference the table below. - -| | Monitor | Relay Operators | -|----------|---------|-----------------| -| rtt | x | | -| nip11 | x | x | -| dns | x | x | -| geo | x | x | -| ssl | x | | -| count | x | x | -| other | x | x | - #### Methodology -A _Relay Monitor_ publishes `30066` events exclusively when a relay is reachable. This approach ensures that the last known active state of the relay is maintained and recorded in `created_at` value of event. Based on this data, several inferences can be drawn about the relay's status and characteristics. -1. Clients and/or users can set a custom threshold to establish a cutoff timestamp for filtering events using `since`. This timestamp helps in identifying which relays are currently online. Selecting a lower threshold value results in a stricter criterion for relay uptime, making the filter more sensitive to brief downtimes. Conversely, choosing a higher threshold value creates a more lenient filter, allowing relays with longer downtimes to still be considered as online. +##### Monitors +1. A _Relay Monitor_ checks the liveness of a relay at the `frequency` defined in their `10166`. -2. In determining whether a relay is 'dead,' the decision is solely at the discretion of the client or user. The are responsible for setting and applying arbitrary thresholds using `until` filters or post-processing to make this determination. This approach underscores that the classification of a relay as 'dead' is a subjective decision, varying according to each client's or user's assessment criteria, rather than a fixed status provided by the monitor. +2. _Relay Monitor_ publishes a kind `30166` note when a relay it is monitoring is online. -3. For [Relay Metadata](#k30066) events that have become outdated, the retained data points remain valuable. They offer insights and information about the relay's characteristics, performance and impact on the network, which might not be currently accessible due to the relay being offline. +_Relay Monitors that publish `30166` events **SHOULD** at a minimum be checking that the relay is available by websocket and behaves like a relay_ -#### Important Notes -- Relay Monitors **SHOULD** run checks and publish events according to the `frequency` value set in their respective `10166` kind event. -- If a relay monitor publishes both `30166` and `30066` kind events, they **SHOULD** publish both on every check. -- Clients **SHOULD** only use monitors reporting `rtt` values for websockets (particularly `open`) for determining the "liveness" or "deadness" of a relay. -- Clients **SHOULD** consider the `frequency` value in a monitor's `10166` when trying to reach determination of "liveness". -- `NIP-11` values are provided as means to filter and discover relays, however ****SHOULD NOT** be used as a replacement to `NIP-11`. -- A particular relay's retention policy could conflict with subjective thresholds used in determination of "liveness" or "deadness" of relays and so care **SHOULD** be taken with regards to chosen relays for `NIP-66` by both monitors and consumers. +##### 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`. -#### Examples +2. _Relay Liveness_ is subjectively determined by the client, starting with the `frequency` value of a monitor. -##### Minimum Requirements -_"Relay was online at ``"_ -```json -{ - "id": "", - "pubkey": "", - "created_at": "", - "signature": "", - "content": "", - "kind": 30066, - "tags": [ - ["d","wss://some.relay/"] - ] -} -``` +3. The liveness of a _Relay Monitor_ can be subjectively determined by detecting whether the _Relay Monitor_ has published events within the specified `frequency`. -##### Relay is checked and online -_"Relay was online at and here's some meta-data this monitor believes is accurate"_ -```json -{ - "id": "", - "pubkey": "", - "created_at": "", - "signature": "", - "content": "{\"contact\":\"pablof7z.com\",\"description\":\"Nostr's Purple Pages\",\"name\":\"purplepag.es\",\"pubkey\":\"fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52\",\"software\":\"git+https://github.com/hoytech/strfry.git\",\"supported_nips\":[1,2,4,9,11,12,16,20,22,28,33,40],\"version\":\"0.9.6-7-g7196547\"}", - "kind": 30066, - "tags": [ - ["d","wss://some.relay/"], - ["other", "network", "clearnet"] - ["rtt", "open", "190", "201", "540"], - ["rtt", "read", "35"], - ["rtt", "write", "701"], - ["nip11", "name", "A nostr relay"], - ["nip11", "description", "It stores notes and other stuff"], - ["nip11", "owner", ""], - ["nip11", "software", ""], - ["nip11", "version", ""], - ["ssl", "valid_from", ""], - ["ssl", "valid_to", ""], - ["geo", "geohash", "ww8p1r4t8"], - ["geo", "countryCode", "NL"], - ["dns", "asn", "19281"], - ["dns", "as", "QUAD9-AS-1, CH"], - ["dns", "ipv4", "1.1.1.1"], - ["dns", "ipv6", "2001:db8:3333:4444:5555:6666:7777:8888"], - ["count", "users_total_active", "201", "86400"], - ["count", "note_total_zaps", "87", "86400"], - ["count", "note_total_reactions", "125", "86400"], - ["count", "note_publish_rate", "24.1", "3600"] - ] -} -``` - -#### Testing Criteria -The testing criteria to determine conditions defined in event's tags **MAY** be subjective and **MAY** vary between monitors. - -#### Limitations -The data in `30066` **MAY** be erroneous, intentionally or otherwise. Where accuracy is required, the data in `30066` events **SHOULD** be subscribed to by populating the `authors` filter array with the public keys of subjectively **trusted monitors** and where security or privacy is a concern any republished values (such as NIP-11 values) should instead be attained from the source (https). All data is for informational purposes and to make finding and filtering through relays through nostr a possiblity. - -## Ammending NIP-66 -Any test results that cannot be expressed through `NIP-66` **should** be ammended to the nip following discussion and general consensus +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 Improvement Proposals (NIPs), ensuring compatibility with desired protocol features. +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, helping users find cost-effective or no-cost options for their network interactions. +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, ensuring the accuracy and reliability of relay data. +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. **Security and Compliance Checks**: Evaluate relays for adherence to security standards and regulatory compliance, essential for users with specific security and privacy requirements. +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. -9. **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. - -10. **Data-Driven Relay Selection**: Make informed choices about which relays to connect to, based on comprehensive metadata including user counts, event frequencies, network types and more. \ No newline at end of file +## 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._ \ No newline at end of file From 42c510183434809b729557d25c403cfe2ca1e7fa Mon Sep 17 00:00:00 2001 From: dskvr Date: Thu, 29 Aug 2024 15:18:39 +0200 Subject: [PATCH 31/34] minor update to k tag that provides support for blocked kinds. --- 66.md | 51 +++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/66.md b/66.md index 2add0f28..158ad63b 100644 --- a/66.md +++ b/66.md @@ -5,6 +5,7 @@ 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": "", @@ -21,8 +22,8 @@ In its purest form: ] } ``` -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. +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` @@ -34,8 +35,8 @@ This NIP defines two (2) event kinds, `10166` and `30166` ## 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. +- `Monitor Service`: a group or individual that monitors relays +- `Monitor`: a piece of software that aggregates relay 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 @@ -159,7 +160,7 @@ _Other `rtt` values **MAY** be present. This NIP should be updated if there is v - `N`: Supported Nips _From NIP-11 "Informational Document" `nip11.supported_nips[]`_ ```json - [ "N", "33" ] + [ "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_ @@ -170,7 +171,7 @@ _Other `rtt` values **MAY** be present. This NIP should be updated if there is v 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", "!payment" ], //no payment required, is public [ "R", "!auth" ], //no authentication required ``` @@ -179,13 +180,21 @@ _Other `rtt` values **MAY** be present. This NIP should be updated if there is v [ "t", "nsfw" ] ``` -- `k`: Accepted Kinds +- `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" ] @@ -233,32 +242,6 @@ _Relay Monitors that publish `30166` events **SHOULD** at a minimum be checking 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`. +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. - -## 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._ \ No newline at end of file +4. The reliability and trustworthiness of a _Relay Monitor_ could be established via web-of-trust, reviews or similar mechanisms. \ No newline at end of file From a109ea7762ae95ed4b61c52e12e9b65c8aa4c9e7 Mon Sep 17 00:00:00 2001 From: dskvr Date: Fri, 30 Aug 2024 18:19:28 +0200 Subject: [PATCH 32/34] language update --- 66.md | 209 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 106 insertions(+), 103 deletions(-) diff --git a/66.md b/66.md index 158ad63b..532ce58c 100644 --- a/66.md +++ b/66.md @@ -8,122 +8,42 @@ In its purest form: ```json { - "sig": "", - "pubkey": "", - "id": "", - "content": "{}", - "created_at": 1722173222, "kind": 30166, + "created_at": 1722173222, + "content": "{}", "tags": [ - [ - "d", - "wss://eostagram.com/" - ] - ] + [ "d", "wss://somerelay.abc/" ] + ], + "pubkey": "", + "sig": "", + "id": "" } ``` -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. +This event signals that the relay at `wss://somerelay.abc/` 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` +`NIP-66` defines two (2) event kinds, `30166` and `10166` | 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 | +| [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 Service`: a group or individual that monitors relays -- `Monitor`: a piece of software that aggregates relay data and publishes that data at a specified frequency. +- `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. -## `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. +Discovery of relays over nostr. ### Schema @@ -143,7 +63,7 @@ The `created_at` field in a NIP-66 event should reflect the time when the relay _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) +- `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/"] ``` @@ -228,20 +148,103 @@ _Relay was online, and you can filter on a number of different tags_ } ``` -#### Methodology +## `10166`: "Relay Monitor Announcement" Events -##### Monitors -1. A _Relay Monitor_ checks the liveness of a relay at the `frequency` defined in their `10166`. +### 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. -2. _Relay Monitor_ publishes a kind `30166` note when a relay it is monitoring is online. +### 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. -_Relay Monitors that publish `30166` events **SHOULD** at a minimum be checking that the relay is available by websocket and behaves like a relay_ +### Schema -##### 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`. +#### 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": "", + "pubkey": "", + "created_at": "", + "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 staticly or dynamically chosen 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. \ No newline at end of file +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. \ No newline at end of file From fa73074f9eda2486d6ed2252da4ee22353391152 Mon Sep 17 00:00:00 2001 From: Sandwich <299465+dskvr@users.noreply.github.com> Date: Fri, 13 Sep 2024 03:25:06 +0200 Subject: [PATCH 33/34] content SHOULD contain stringified NIP-11 --- 66.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/66.md b/66.md index 532ce58c..325a80e3 100644 --- a/66.md +++ b/66.md @@ -48,7 +48,7 @@ Discovery of relays over nostr. ### 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. +`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. @@ -247,4 +247,4 @@ _Any pubkey that publishes `30166` events **SHOULD** at a minimum be checking th - 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. \ No newline at end of file +- 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. From cc3d7c63f59631810032c14d1f56ff034084583e Mon Sep 17 00:00:00 2001 From: Sandwich <299465+dskvr@users.noreply.github.com> Date: Tue, 17 Sep 2024 19:39:10 +0200 Subject: [PATCH 34/34] Fix typos --- 66.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/66.md b/66.md index 325a80e3..b242e856 100644 --- a/66.md +++ b/66.md @@ -235,7 +235,7 @@ Monitors **SHOULD** have the following _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 staticly or dynamically chosen 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. +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.