mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-22 16:35:52 -05:00
add nostr groups draft
This commit is contained in:
parent
badabd513e
commit
db69e5fc5a
236
100.md
Normal file
236
100.md
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
NIP-100
|
||||||
|
======
|
||||||
|
|
||||||
|
Nostr Groups
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
`draft` `optional` `author:DanConwayDev`
|
||||||
|
|
||||||
|
groups managed by evolving sets of Administrators with verifiable histories.
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
This enables trust-minimised verification that an account was a member of a group at a specific point of time, even when the Administrators of that group evolves over time.
|
||||||
|
|
||||||
|
Useful for authorisation in asynchronous distributed systems in scenarios where:
|
||||||
|
1. provisional authorisation states can be acted upon
|
||||||
|
1. these changes are medimum-to-low-frequency
|
||||||
|
1. its acceptable that these changes may take hours to confirm
|
||||||
|
|
||||||
|
## Group Events
|
||||||
|
|
||||||
|
Group Event Types:
|
||||||
|
|
||||||
|
| Kind | | Description |
|
||||||
|
|--------|--------------|-------------------|
|
||||||
|
| `xxx` | `init_group` | Initialize group |
|
||||||
|
| `xxx` | `group_modification_proposal` | |
|
||||||
|
| `xxx` | `vote` | approve / reject |
|
||||||
|
| `xxx` | `group_modification` | |
|
||||||
|
| `xxx` | `attest` | provide the OpenTimestamps for a note and / or attest a note has been broadcast |
|
||||||
|
|
||||||
|
## Group State
|
||||||
|
|
||||||
|
The state of a group at a point in time is constructed from the `init_group` event and the subsequent chain of modificaitons actioned through `proposal` and`group_modification` events.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
|
||||||
|
"id": <id of init_group>,
|
||||||
|
"members": [
|
||||||
|
<member's pubkey>,
|
||||||
|
[
|
||||||
|
<id of init_group to nest>,
|
||||||
|
[optional]"groupvote" (limits voting power to 1 vote for group)
|
||||||
|
],
|
||||||
|
...
|
||||||
|
],
|
||||||
|
"chaintip": <id of last group_modification applied>
|
||||||
|
"admin": <admin init_group note id> | null,
|
||||||
|
[optional]"meta": {... mirrors set_metadata (NIP-01)},
|
||||||
|
[optional]"broadcast-attesters": [
|
||||||
|
<pubkey>
|
||||||
|
] | null,
|
||||||
|
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Making Modifications
|
||||||
|
|
||||||
|
Changes can be permissionlessly proposed using `group_modification_proposal` events.
|
||||||
|
|
||||||
|
Proposals or direct modifications can be actioned by an Administrator through `group_modification` events.
|
||||||
|
|
||||||
|
Modifications are treated as provisional until attestation is recieved.
|
||||||
|
|
||||||
|
#### Administrator Removal
|
||||||
|
|
||||||
|
The only modification that requires additional authorisation is the removal, or limiting of voting rights, of one or more Administrators who have held the role continuously for 7 day or more. This happens through voting. This modification requires either:
|
||||||
|
1. their vote(s) cast in favor
|
||||||
|
1. a super majority of potential votes
|
||||||
|
1. a simple majority of potential votes if 10 days have elapsed and no votes have provabilty been cast against the proposal
|
||||||
|
|
||||||
|
The change is actioned through a `group_modification` event which references the proposal and sufficent votes.
|
||||||
|
|
||||||
|
The proposal is deemed rejected without a simple majority after 10 days or being action after 30 days.
|
||||||
|
|
||||||
|
These Administrators are suspended from submitting `group_modifications` for the duration of the vote if both:
|
||||||
|
1. the proposal was authored by an Administrator
|
||||||
|
1. proposed removals cover only a minority of Administrators
|
||||||
|
|
||||||
|
Their voting rights remain uneffected.
|
||||||
|
|
||||||
|
### Definitions
|
||||||
|
|
||||||
|
Members: accounts listed directly in the Group State `members` array and Members of groups referenced there in.
|
||||||
|
|
||||||
|
Administrator: The Administrators of the group referenced the Group State `admin` property. If null, accounts listed directly in the Group State `members` array and Administrators of groups referenced there in.
|
||||||
|
|
||||||
|
Voter: Any account that has held the Administrator role continously for 10 days prior to the proposal timestamp or an account that has held that role within the last 10 days who has also held the role for at least 30 days.
|
||||||
|
|
||||||
|
### Optional Attestation
|
||||||
|
|
||||||
|
To prevent the key of an (ex)Administrator broadcasting a competing chain of modifications that undermines the Group State, we must verify that each event has been broadcast before it is confirmed. This is achieved through:
|
||||||
|
|
||||||
|
1. trustless proof-of-existance through OpenTimestamps (NIP-03 or `attest` note)
|
||||||
|
1. attestation of publication by at least one trusted third-party (required only if `broadcasted-event-attesters` is not `null`)
|
||||||
|
|
||||||
|
If a chain split occurs, the chain containing the smallest
|
||||||
|
`Attestation Adjusted Timestamp` is the only valid chain. This is defined as:
|
||||||
|
|
||||||
|
```
|
||||||
|
***TODO - insert formula relating m, b and p *** + (1 / pk)
|
||||||
|
|
||||||
|
m = <timestamp of modification event>
|
||||||
|
b = <timestamp embedded into the blockheader of the earliest valid OpenTimestamp formatted as unix timestamp in seconds.
|
||||||
|
p = smallest timestamp of attestation of publication event
|
||||||
|
pk = authors public key
|
||||||
|
```
|
||||||
|
|
||||||
|
Groups can be used without, or with infrequent, attestation with a reduced trust model.
|
||||||
|
|
||||||
|
## Group Events
|
||||||
|
|
||||||
|
### Event `xxx` `init_group`
|
||||||
|
|
||||||
|
content is stringified:
|
||||||
|
```json
|
||||||
|
"members": [
|
||||||
|
<member's pubkey>,
|
||||||
|
[
|
||||||
|
<id of init_group to nest>,
|
||||||
|
[optional]"groupvote" (limits voting power to 1 vote for group)
|
||||||
|
],
|
||||||
|
...
|
||||||
|
],
|
||||||
|
"admin": <admin init_group event id> | null,
|
||||||
|
[optional]"meta": {... mirrors set_metadata (NIP-01)},
|
||||||
|
[optional]"broadcast-attesters": [
|
||||||
|
<pubkey>
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Event `xxx` `group_modification_proposal`
|
||||||
|
|
||||||
|
|
||||||
|
```json
|
||||||
|
"tags": [
|
||||||
|
["group", <id of init_group note>],
|
||||||
|
["parent", <id of the previous group_modification in the chain or init_group if first group_modification],
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
content:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[optional]"remove":[<position in array>,...],
|
||||||
|
[optional]"add":[<member's pubkey>,...],
|
||||||
|
[optional]"admin":<id of init_group note> | null,
|
||||||
|
[optional]"meta":{
|
||||||
|
<key to be updated>: <new key value>
|
||||||
|
}
|
||||||
|
[optional]"broadcast-attesters": [
|
||||||
|
<pubkey>,
|
||||||
|
...
|
||||||
|
] | null
|
||||||
|
```
|
||||||
|
|
||||||
|
This also acts as a vote for the proposal, if the author has voting rights.
|
||||||
|
|
||||||
|
Timestamp must be greater than that of it's `parent`.
|
||||||
|
|
||||||
|
## Event `xxx` `vote`
|
||||||
|
|
||||||
|
```json
|
||||||
|
"tags": [
|
||||||
|
["group", <id of init_group note>],
|
||||||
|
["proposal", <id of group_modification_proposal],
|
||||||
|
]
|
||||||
|
"content:"true" or "false"
|
||||||
|
```
|
||||||
|
|
||||||
|
Considered invalid by supported client if the author has no voting rights.
|
||||||
|
|
||||||
|
Timestamp must be greater than that of the referenced `proposal`.
|
||||||
|
|
||||||
|
|
||||||
|
## Event `xxx` `group_modification`
|
||||||
|
|
||||||
|
tags:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"tags": [
|
||||||
|
["group", <id of init_group note>],
|
||||||
|
["parent", <id of the previous group_modification in the chain or init_group if first group_modification],
|
||||||
|
[optional]["proposal", <id of a group_modification_proposal being implemented],
|
||||||
|
[optional]["vote", <id of vote>],
|
||||||
|
[optional]["vote", <id of vote>],
|
||||||
|
[optional]["proposal", <id of a second group_modification_proposal being implemented],
|
||||||
|
[optional]["vote", <id of vote>],
|
||||||
|
[optional]["vote", <id of vote>],
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
One or more `group_modification_proposal`'s are considered implemented when first referenced in the `proposal` tag in combination with sufficent valid `vote` events referenced using the `vote` tag.
|
||||||
|
|
||||||
|
A `group_modification` event is considered a `vote` for a proposal if referenced alongside an otherwise sufficent number of votes.
|
||||||
|
|
||||||
|
proposals are implemented in the order that they appear in `tags`.
|
||||||
|
|
||||||
|
proposed changed are merged with current state before any changes in `content` are implemented.
|
||||||
|
1. array index positions references adapted from the pre-proposal state to match the corresponding item in the.
|
||||||
|
1. if a proposal contains an instruction to add/remove a member, but before it is implemented the member is added/removed by another `group_modification` event, this specific instruction is ignored. The member is not added an additional time (which could increase their voting powers).
|
||||||
|
|
||||||
|
content:
|
||||||
|
|
||||||
|
```json
|
||||||
|
|
||||||
|
[optional]"remove":[<position in array>,...],
|
||||||
|
[optional]"add":[<member's pubkey>,...],
|
||||||
|
[optional]"meta":{
|
||||||
|
<key to be updated>: <new key value>
|
||||||
|
}
|
||||||
|
[optional]"broadcast-attesters": [
|
||||||
|
<pubkey>,
|
||||||
|
...
|
||||||
|
] | null
|
||||||
|
```
|
||||||
|
|
||||||
|
Changes in a proposal being implemented should not be listed in the `content`.
|
||||||
|
|
||||||
|
Members cannot be removed directly using this event if `admin` is `null` in the current Group State. This is because Members are also Administrators in that instance.
|
||||||
|
|
||||||
|
Timestamp must be greater than that of it's `parent`.
|
||||||
|
|
||||||
|
## Event `xxx` `attest`
|
||||||
|
|
||||||
|
```json
|
||||||
|
"tags": [
|
||||||
|
["group", <id of init_group note>],
|
||||||
|
["e", <id of note to attest>],
|
||||||
|
],
|
||||||
|
"content:"",
|
||||||
|
[optional]"attested-ots": <base64-encoded OTS file data of attested note>
|
||||||
|
```
|
Loading…
Reference in New Issue
Block a user