nips/0A.md
Mike Dilger a58e71bcab
more
2025-01-03 09:20:22 +13:00

141 lines
5.8 KiB
Markdown

NIP-0A
======
Synchronized Contact List
-------------------------
An addressable event with kind `33000` means "follow list" which communicates the set of profiles (represented by public keys) that the author is currently following.
The term "following" is left undefined, see ["Uses"](#uses).
The public keys followed are specified in "p" tags.
Additional "np" tags are present only to help with synchronization as described below.
A "d" tag is specified to indicate the client (or possibly client installation) that created the event. This helps prevent cross-client clobbers.
The `.content` is not used.
## Event Tags
### p tags
Each profile followed is reprsented in a "p" tag as follows:
```
["p", <pubkey>, <relay>, <petname>, <timestamp>]
```
Where
* `pubkey` is the hex encoded public key of the profile
* `relay` is an optional relay where the `pubkey` is known to post, or an empty string
* `petname` is an optional petname that the author uses for the contact, or an empty string
* `timestamp` is required and is the time when the entry was added to the list
### np tags
"p" tag entries are not removed. Instead they are converted into "np" entries and their timestamp is updated to time that they were considered removed.
```
["np", <pubkey>, <relay>, <petname>, <timestamp2>]
```
Pubkeys MUST only be listed once in either a "p" tag or an "np" tag.
`p` means the person is counted as a contact. `np` means they are not counted as a contact but the entry serves to help remember when they were removed so that conflicts can be resolved.
Note that `np` is not searchable on relays.
## Updates and Publishing
### Ownership (your own list)
When you add a person, you find their entry and if it is an "np", you change it to a "p" and update the timestamp to the current time. If missing, you create the "p" entry.
When you remove a person, you find their entry and if it is a "p", you change it to a "np" and update the timestamp to the current time. If missing, you create the "np" entry.
When you receive your own follow list, you merge it with any previous data you had. If the result changes the previous data you had, then you generate a new kind 33000 event and publish it. See [Merge Operation](#merge-operation) below. This resolves forks.
Clients MUST read the latest follow list from a relay and merge it before writing a newer follow list to minimize the chance of clobbering.
### Observation (other people's lists)
When dealing with other people's follow lists, nothing special needs to be done. These events are complete lists not change sets. The latest event represents the entire set of contacts. Clients do not need to search for and merge multiple events.
### Merge Operation
The merge operation is as follows: On a tag-by-tag basis, if only one event has a line for a pubkey, you accept that line. If both events have a line for that pubkey, you take the line with the largest timestamp.
### Relay to use
These events are published to the author's outbox relays. They shouldn't be delivered to the inboxes of all the people tagged.
### Interaction with kind=3 events
*This section is still being worked out*
Ideas:
* Clients supporting this NIP should consider these newer events to supercede any kind-3 events by the same author.
* For their own user's follow list, if a kind-3 event is found that is newer than the newest kind-33000 event, clients can choose what to do about that (this is not an easy situation to resolve).
* If there is no kind-33000 event available, clients should migrate data from the latest kind-3 event to the first kind-33000 event.
* Clients supporting this NIP should also publish kind-3 events that reflect the latest follow list whenever they publish kind-33000 events.
## Uses
### Feed Generation
Clients may use this list to generate feeds including only (or prefentially) these authors.
### Follow list backup
If one believes a relay will store their events for sufficient time, they can use this kind-33000 event to backup their following list and recover on a different device.
### Profile discovery and context augmentation
A client may rely on the kind-33000 event to display a list of followed people by profiles one is browsing; make lists of suggestions on who to follow based on the follow lists of other people one might be following or browsing; or show the data in other contexts.
### Relay sharing
A client may publish a follow list with good relays for each of their follows so other clients may use these to update their internal relay lists if needed, increasing censorship-resistance.
### Petname scheme
The data from these follow lists can be used by clients to construct local ["petname"](http://www.skyhunter.com/marcs/petnames/IntroPetNames.html) tables derived from other people's follow lists. This alleviates the need for global human-readable names. For example:
A user has an internal follow list that says
```json
[
["p", "21df6d143fb96c2ec9d63726bf9edc71", "", "erin"]
]
```
And receives two follow lists, one from `21df6d143fb96c2ec9d63726bf9edc71` that says
```json
[
["p", "a8bb3d884d5d90b413d9891fe4c4e46d", "", "david"]
]
```
and another from `a8bb3d884d5d90b413d9891fe4c4e46d` that says
```json
[
["p", "f57f54057d2a7af0efecc8b0b66f5708", "", "frank"]
]
```
When the user sees `21df6d143fb96c2ec9d63726bf9edc71` the client can show _erin_ instead;
When the user sees `a8bb3d884d5d90b413d9891fe4c4e46d` the client can show _david.erin_ instead;
When the user sees `f57f54057d2a7af0efecc8b0b66f5708` the client can show _frank.david.erin_ instead.
## Rationale
This functionally implements a Last-Write-Wins Element Set, which is a conflict-free replicated data set with eventual consistency.
We use replaceable events so that superceded events can be erased by relays. This brings back a per-relay clobbering issue, and so we use addressable events to limit such clobbering.