Simplify text and replace nip34 namespace with 'algo'

This commit is contained in:
arthurfranca 2023-09-22 10:12:16 -03:00
parent 6fac0f53f5
commit ad6ee17624
3 changed files with 45 additions and 115 deletions

100
34.md
View File

@ -6,72 +6,62 @@ Algorithmic Filter
`draft` `optional` `author:arthurfranca`
This NIP introduces a set of simple algorithms meant to support diverse apps' event sorting needs.
`Relays` MUST store an extra event field for each algo. Today there are two: `asc` and `seen_at`.
According to [NIP-01](01.md), filters with `limit` attribute are replied with events
sorted in **descending** order by the `created_at` event field (newest events first).
For filters containing `limit` attribute, this NIP-34 adds `nip34` as a new filter attribute
whose value indicates the algorithm the `client` wishes to use for sorting events.
For instance, if a `client` sends the message `["REQ", <sub_id>, { kinds: [1], ..., limit: 5, nip34: "a" }]`,
it is asking the `relay` to sort five kind 1 events in **descending** order by the `nip34a` event field instead of by `created_at`.
In the above example, `relays` that want to support the NIP-34a algorithm must add the `nip34a` event field to each event saved to their internal databases. The new field is populated following rules described at the NIP-34a NIP extension.
Besides that, upon replying to such requests, the supporting `relay` MUST add `nip34: { score: "<nip34a value>" }` field to each returned event JSON.
It is a backward-compatible proposal because non-supporting `relays` ignore the `nip34` filter attribute and sort by `created_at`, as usual.
`Relays` should advertise support using both [NIP-11](11.md) `supported_nips` and `supported_nip_extensions` fields.
`Relays` should limit max daily user events, such as likes, reposts, zaps and comments, per IP to avoid bad actors gaming the algorithms.
## Motivation
Different algorithms are required to support diverse apps' event sorting needs.
However, they should be presented as optional and backward-compatible features that are easy to support.
Considering the request example above, we expect most `relays` to simply swap the `created_at` field
on a regular query for the `nip34a` one. If a `relay` implementation uses a SQL DB, the above filter would turn this:
But now when a `client` requests events while filtering by an algo field, the `relay` MUST replace the `created_at` field in the query with the algo field. For example, a SQL relay should turn this:
`SELECT * FROM events WHERE kind in (1) ORDER BY created_at DESC LIMIT 5`
Into this:
`SELECT * FROM events WHERE kind in (1) ORDER BY nip34a DESC LIMIT 5`
`SELECT * FROM events WHERE kind in (1) ORDER BY asc DESC LIMIT 5`
Upon replying to such requests, the supporting `relay` MUST add `algo: { score: "<asc value>" }` field to each returned event JSON.
## Querying
An extra `algo` filter key holds the selected algorithm as value. For example, the above
query is ran in response to the following request:
`["REQ", <sub_id>, { kinds: [1], limit: 5, algo: "asc" }]`
## Algorithms
### Asc
`Relay` computes `asc` field once upon receiving the event. The lower the `created_at`, the higher `asc` will be.
```js
function getAsc (createdAt) {
const maxDateNowSeconds = 8640000000000 // 8.64e15 ms / 1000
// Make it lower the greater the ts is (the newer the createdAt is)
// maxDateNowSeconds - -maxDateNowSeconds equals 17280000000000 and is lower than Number.MAX_SAFE_INTEGER
return maxDateNowSeconds - createdAt
}
event.asc = getAsc(event.created_at)
```
### Seen At
`Relay` computes `seen_at` field once upon receiving the event. The event field is set with the timestamp of the moment the `relay` first became aware of it, in seconds.
```js
event.seen_at = Math.floor(Date.now() / 1000)
```
## Relay Connection URL Query Parameter
For each supported NIP-34 algorithm, the `relay` MUST allow `clients` to specify the algo as a `nip34` query param on connection URL string.
For each algorithm, the `relay` MUST allow `clients` to specify the algo as an `algo` query param on the connection URL string.
For example, if supporting the NIP-34a algo, a `relay` whose regular URL is `wss://relay.url/r1` must
also respond at `wss://relay.url/r1?nip34=a`.
In other words, a `relay` whose regular URL is `wss://relay.url/r1` MUST also respond at `wss://relay.url/r1?algo=asc` and `wss://relay.url/r1?algo=seen_at`.
Then when `clients` connect to `wss://relay.url/r1?nip34=a` and request events using `limit`
filter attribute, the relay will automatically sort events in **descending** order by the `nip34a` event field instead of by `created_at` when replying. Clients can still override the chosen algorithm if using the
`nip34` filter attribute.
Then, for example, when `clients` connect to `wss://relay.url/r1?algo=asc` and request events using the `limit`
filter attribute, the relay will automatically sort events using the `asc` event field instead of the `created_at` one when replying.
## How Clients Make Custom Requests for a Specific User
The algorithms are generic, meaning the "score" represented by the new event field does not differ for different users.
However, smart `clients` may keep track of pubkeys from whom the user is consuming content, also hashtags, for instance, and use such pubkeys/hashtags as a way to tailor the query to that specific user. For example:
`["REQ", <sub_id>, { kinds: [1], limit: 5, nip34: "b", authors: ["pubkey1 user follows", "pubkey2 user has read content from recently", "pubkey3 that user has liked content recently"] }, { kinds: [1], limit: 5, nip34: "b", "#t": ["cat", "bitcoin"] }]`
## Rules for Submitting a NIP-34 Algorithm
Each algorithm section describes **how** and **when** to compute the corresponding database field for each event.
For example, [NIP-34asc](34asc.md) extension teaches `relays` the math used to update the `nip34asc` event field.
The NIP extension MUST have atleast one example in any programming language, preferably with inline comments.
Bugfixes and small updates to embrace new event kinds may be submitted at any time by the algorithm author(s).
## Available Algorithms
| Extension | Name | Description | Modification Date |
| ------------------- | ----------| -------------------------------------------------- | ----------------- |
| [34asc](34asc.md) | Ascending | Events with older `created_at` are retrieved first | 18 / jul / 2023 |
| [34seen](34seen.md) | Seen At | Events are desc sorted by first seen at timestamp | 18 / jul / 2023 |
Clients can still override the chosen algorithm if using the `algo` filter attribute on `REQ` messages.

View File

@ -1,34 +0,0 @@
NIP-34asc
=========
Ascending
---------
`draft` `optional` `author:arthurfranca`
Events with older `created_at` are retrieved first.
## Motivation
For thread building it may better showing first comments at top to make it easier to understand
the context of newer comments.
## Implementation
`Relay` computes `nip34asc` field once upon receiving the event.
The lower the `created_at`, the higher `nip34asc` will be.
### Javascript
```js
function getNip34asc (createdAt) {
const maxDateNowSeconds = 8640000000000 // 8.64e15 ms / 1000
// Make it lower the greater the ts is (the newer the createdAt is)
// maxDateNowSeconds - -maxDateNowSeconds equals 17280000000000 and is lower than Number.MAX_SAFE_INTEGER
return maxDateNowSeconds - createdAt
}
event.nip34asc = getNip34asc(event.created_at)
```

View File

@ -1,26 +0,0 @@
NIP-34seen
==========
Seen At
-------
`draft` `optional` `author:arthurfranca` `author:mikedilger`
Events are desc sorted by first seen at timestamp.
## Motivation
Some `clients` may want to check if `relay` has recently received old events
created before last time they checked.
## Implementation
`Relay` computes `nip34seen` field once upon receiving the event.
The event field is set with the timestamp of the moment the `relay` first became aware of it.
### Javascript
```js
event.nip34seen = Math.floor(Date.now() / 1000)
```