From 15514283f3a5c51e21e596ff413da2ccc4a70b6e Mon Sep 17 00:00:00 2001 From: William Casarin Date: Thu, 10 Nov 2022 10:07:13 -0800 Subject: [PATCH 1/6] NIP-20: Command Results When submitting events to relays, clients currently have no way to know if an event was successfully committed to the database. This NIP introduces the concept of command results which are like NOTICE's except provide more information about if an event was accepted or rejected. --- 20.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 65 insertions(+) create mode 100644 20.md diff --git a/20.md b/20.md new file mode 100644 index 00000000..1f06fa95 --- /dev/null +++ b/20.md @@ -0,0 +1,63 @@ +NIP-20 +====== + + +Command Results +--------------- + +`draft` `optional` `author:jb55` + +When submitting events to relays, clients currently have no way to know if an event was successfully committed to the database. This NIP introduces the concept of command results which are like NOTICE's except provide more information about if an event was accepted or rejected. + +A command result is a JSON object with the following structure that is returned when an event is successfully saved to the database or rejected: + + ["OK", , , ] + +Relays MUST return `true` when the event is a duplicate and has already been saved. The `message` SHOULD start with `duplicate:` in this case. + +Relays MUST return `false` when the event was rejected and not saved. + +The `message` SHOULD provide additional information as to why the command succeeded or failed. + +The `message` SHOULD start with `blocked:` if the pubkey or network address has been blocked, banned or is not on a whitelist. + +The `message` SHOULD start with `rate-limited:` if the event was rejected due to rate limiting techniques. + +Ephemeral events are not acknowledged with OK responses, unless there is a failure. + +If the event is malformed and could not be parsed, a NOTICE message SHOULD be used instead of a command result. + + +Examples +-------- + +Event successfully written to the database: + + ["OK", "b1a649ebe8b435ec71d3784793f3bbf4b93e64e17568a741aecd4c7ddeafce30", true, ""] + +Event successfully written to the database because of a reason: + + ["OK", "b1a649ebe8b435ec71d3784793f3bbf4b93e64e17568a741aecd4c7ddeafce30", true, "pow: difficulty 25>=24"] + +Event blocked due to ip filter + + ["OK", "b1a649ebe8...", false, "blocked: tor exit nodes not allowed"] + +Event blocked due to pubkey ban + + ["OK", "b1a649ebe8...", false, "blocked: you are banned from posting here"] + +Event blocked, pubkey not registered + + ["OK", "b1a649ebe8...", false, "blocked: please register your pubkey at https://my-expensive-relay.example.com"] + +Event rejected, rate limited + + ["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"] + + + +Future Extensions +----------------- + +This proposal SHOULD be extended to support futher commands in the future, such as REQ and AUTH. They are left out of this initial version to keep things simpler. diff --git a/README.md b/README.md index d974dd3b..8b3a9946 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh - [NIP-14: Subject tag in text events.](14.md) - [NIP-15: End of Stored Events Notice](15.md) - [NIP-16: Event Treatment](16.md) +- [NIP-20: Command Results](20.md) - [NIP-22: Event created_at Limits](22.md) - [NIP-25: Reactions](25.md) - [NIP-28: Public Chat](28.md) @@ -58,6 +59,7 @@ NIPs stand for **Nostr Implementation Possibilities**. They exist to document wh | EVENT | used to send events requested to clients | [1](01.md) | | NOTICE | used to send human-readable messages to clients | [1](01.md) | | EOSE | used to notify clients all stored events have been sent | [15](15.md) | +| OK | used to notify clients if an EVENT was successuful | [20](20.md) | Please update these lists when proposing NIPs introducing new event kinds. From a0b0a021a86b3433f8ce331e85091b6d8c90b4ef Mon Sep 17 00:00:00 2001 From: William Casarin Date: Thu, 10 Nov 2022 11:57:13 -0800 Subject: [PATCH 2/6] NIP-20: add "invalid" message suggestion --- 20.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/20.md b/20.md index 1f06fa95..447b10a0 100644 --- a/20.md +++ b/20.md @@ -21,6 +21,8 @@ The `message` SHOULD provide additional information as to why the command succee The `message` SHOULD start with `blocked:` if the pubkey or network address has been blocked, banned or is not on a whitelist. +The `message` SHOULD start with `invalid:` if the event doesn't meet some specific criteria (created_at is too far off, etc) + The `message` SHOULD start with `rate-limited:` if the event was rejected due to rate limiting techniques. Ephemeral events are not acknowledged with OK responses, unless there is a failure. @@ -55,6 +57,10 @@ Event rejected, rate limited ["OK", "b1a649ebe8...", false, "rate-limited: slow down there chief"] +Event rejected, `created_at` too far off + + ["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time. Is your system clock in sync?"] + Future Extensions From e7f74d21c48e255181d93eda317f36f9702a14ad Mon Sep 17 00:00:00 2001 From: William Casarin Date: Thu, 10 Nov 2022 12:02:14 -0800 Subject: [PATCH 3/6] NIP-20: pow suggestion --- 20.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/20.md b/20.md index 447b10a0..e76942ab 100644 --- a/20.md +++ b/20.md @@ -23,6 +23,8 @@ The `message` SHOULD start with `blocked:` if the pubkey or network address has The `message` SHOULD start with `invalid:` if the event doesn't meet some specific criteria (created_at is too far off, etc) +The `message` SHOULD start with `pow:` if the event doesn't meet some proof-of-work difficulty. The client MAY consult the relay metadata at this point to retrieve the required posting difficulty. + The `message` SHOULD start with `rate-limited:` if the event was rejected due to rate limiting techniques. Ephemeral events are not acknowledged with OK responses, unless there is a failure. @@ -61,6 +63,9 @@ Event rejected, `created_at` too far off ["OK", "b1a649ebe8...", false, "invalid: event creation date is too far off from the current time. Is your system clock in sync?"] +Event rejected, insufficient proof-of-work difficulty + + ["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"] Future Extensions From 7569773ad6e162333155905f9f1ea620c732ff71 Mon Sep 17 00:00:00 2001 From: William Casarin Date: Thu, 10 Nov 2022 12:14:18 -0800 Subject: [PATCH 4/6] NIP-20: add a note about client handling --- 20.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/20.md b/20.md index e76942ab..9a96f6df 100644 --- a/20.md +++ b/20.md @@ -68,6 +68,19 @@ Event rejected, insufficient proof-of-work difficulty ["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"] + +Client Handling +--------------- + +`messages` are meant for humans, with `reason:` prefixes so that clients can be slightly more intelligent with what to do with them. For example, with a `rate-limited:` reason the client may not show anything and simply try again with a longer timeout. + +For the `pow:` prefix it may query relay metadata to get the updated difficulty requirement and try again in the background. + +For the `invalid:` and `blocked`: prefix the client may wish to show these as styled error popups. + +The prefixes include a colon so that the message can be cleanly separated from the prefix by taking everything after `:` and trimming it. + + Future Extensions ----------------- From ff26b959f8fd9ae9d72ed0f1ebf6ecc67d1fa65a Mon Sep 17 00:00:00 2001 From: William Casarin Date: Thu, 10 Nov 2022 12:55:28 -0800 Subject: [PATCH 5/6] NIP-20: More clarity around malformed vs invalid events --- 20.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/20.md b/20.md index 9a96f6df..8bd7ab57 100644 --- a/20.md +++ b/20.md @@ -21,7 +21,7 @@ The `message` SHOULD provide additional information as to why the command succee The `message` SHOULD start with `blocked:` if the pubkey or network address has been blocked, banned or is not on a whitelist. -The `message` SHOULD start with `invalid:` if the event doesn't meet some specific criteria (created_at is too far off, etc) +The `message` SHOULD start with `invalid:` if the event is invalid or doesn't meet some specific criteria (created_at is too far off, id is wrong, signature is wrong, etc) The `message` SHOULD start with `pow:` if the event doesn't meet some proof-of-work difficulty. The client MAY consult the relay metadata at this point to retrieve the required posting difficulty. @@ -29,7 +29,7 @@ The `message` SHOULD start with `rate-limited:` if the event was rejected due to Ephemeral events are not acknowledged with OK responses, unless there is a failure. -If the event is malformed and could not be parsed, a NOTICE message SHOULD be used instead of a command result. +If the event or `EVENT` command is malformed and could not be parsed, a NOTICE message SHOULD be used instead of a command result. This NIP only applies to non-malformed EVENT commands. Examples From c510e646d0fd5bfa56a044756182cc10ad7e494d Mon Sep 17 00:00:00 2001 From: William Casarin Date: Thu, 10 Nov 2022 13:14:23 -0800 Subject: [PATCH 6/6] NIP-20: server errors happen! --- 20.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/20.md b/20.md index 8bd7ab57..6c81cbe0 100644 --- a/20.md +++ b/20.md @@ -27,6 +27,8 @@ The `message` SHOULD start with `pow:` if the event doesn't meet some proof-of-w The `message` SHOULD start with `rate-limited:` if the event was rejected due to rate limiting techniques. +The `message` SHOULD start with `error:` if the event failed to save due to a server issue. + Ephemeral events are not acknowledged with OK responses, unless there is a failure. If the event or `EVENT` command is malformed and could not be parsed, a NOTICE message SHOULD be used instead of a command result. This NIP only applies to non-malformed EVENT commands. @@ -67,6 +69,10 @@ Event rejected, insufficient proof-of-work difficulty ["OK", "b1a649ebe8...", false, "pow: difficulty 26 is less than 30"] +Event failed to save, + + ["OK", "b1a649ebe8...", false, "error: could not connect to the database"] + Client Handling