Further detail after discussion and thought

This commit is contained in:
Mike Dilger 2024-12-08 09:47:54 +13:00
parent b5a35af15b
commit f5a22ce6e6
No known key found for this signature in database
GPG Key ID: 47581A78D4329BA4

62
0A.md
View File

@ -4,26 +4,62 @@ NIP-0A
Contact List v2
---------------
This is an early draft, I'll flesh out details after discussion.
This is an early draft, I'm still working out the details.
Event tags would look like this:
## Events and Tags
Events have tags like this for each contact:
```
["contact", "<pubkey1>", "in", "<timestamp1>"]
["contact", "<pubkey2>", "out", "<timestamp2>"]
["p", <pubkey1>, <relay>, <petname>, <timestamp1>]
["np", <pubkey2>, <relay>, <petname>, <timestamp2>]
```
Note that they are not 'p' tags, they don't need delivery to the person's INBOX.
But maybe they should be searchable to people can count their "followers".
`p` means the person is counted as a contact. `np` means they are not counted as a contact, but
we are just remembering when they were removed. Note that `np` is not searchable on relays.
When you add a person, you find their entry and change the last two fields to "in" and the current timestamp.
All contacts in the stated range should be listed. These events are complete lists, they are
not change sets.
When you remove a person, you find their entry and change the last two fields to "out" and the current timestamp.
## Owner Handling
When merging two events, you accept the entry with the largest timestamp.
When you add a person, you find their entry and make sure the tag is "p" and not "np" and then you
update the timestamp to the current time. If missing, you create the entry.
Note that we have to keep the "out" entries in case we later get an "in" entry dated earlier, we can
ignore such an add.
When you remove a person, you find their entry and make sure the tag is "np" and not "p" and then
you update the timestamp to the current time. If missing, you create the entry.
This is functionally implements a Last-Write-Wins Element Set, which is a conflict-free replicated data set
with eventual consistency.
When you receive your own contact list (presumably created by a different client), you merge it
with your local one and publish the result. See [Merge Operation](#merge-operation) below.
## Observers
A client that does not store any data can simply accept the latest contact list.
Clients that do store data can instead choose to merge newer contact lists with the data they
already hold for the person's contacts that was created from previous events. The benefit of
doing this is only slight.
## 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.
## Possible Splitting (TBD)
There are four kinds (to be assigned):
kind1 - all contacts whose public keys end with '0' - '3'
kind2 - all contacts whose public keys end with '4' - '7'
kind3 - all contacts whose public keys end with '8' - 'b'
kind4 - all contacts whose public keys end with 'c' - 'f'
NOTE: We could actually continue to use kind3, as the 'timestamp' is additional and would
be ignored by current software, as would the 'np' tags. However that wouldn't allow splitting the
list into four chunks.
## Rationale
This is functionally implements a Last-Write-Wins Element Set, which is a conflict-free replicated
data set with eventual consistency.