nips/76.md
2024-09-13 13:10:20 -04:00

85 lines
2.3 KiB
Markdown

NIP-76
======
Relay Read Permissions
----------------------
`draft` `optional`
Tag names `rp` (read permission) and `prp` (probabilistic read permission) define which keys are authorized to download an event from the relay.
Events that include an `rp` or `prp` require AUTH to be downloaded.
## Read Permission
The `rp` tag accepts a list of pubkeys
```json
["rp", "<pubkey1>", "<pubkey2>", "<pubkey3>"]
```
Relays MUST check if the authed user is one of the keys in the `rp` before sending the event to the client.
## Probabilistic Read Permissions
Probabilistic permissions use bloom filters that include a set of pubkeys. They are represented by a colon-separated value with:
1. the size of the bit array
2. the number of hashing rounds used by the filter
3. the bit array in Base64.
```json
["prp", "<BitArray Size>:<Rounds>:<base64>"]
```
Bloom filters MUST use `SHA-256` functions of the key + iterating index as the psedocode below:
```js
class BloomFilter(size: Int, rounds: Int, buffer: ByteArray) {
val bits = BitArray(buffer)
fun bitIndex(value: ByteArray, index: Byte) {
return BigInt(sha256(value || index)) % size
}
fun add(pubkey: HexKey) {
val value = pubkey.hexToByteArray()
for (index in 0 until rounds) {
bits[bitIndex(value, index)] = true
}
}
fun mightContains(pubkey: HexKey): Boolean {
val value = pubkey.hexToByteArray()
for (index in 0 until rounds) {
if (!bits[bitIndex(value, index)]) {
return false
}
}
return true
}
fun encode() = size + ":" + rounds + ":" + base64Enc(bits.toByteArray()) // base64 might include extra 0 bits to fill the last byte
fun decode(str: String): BloomFilter {
val parts = str.split(":")
return BloomFilter(parts[0].toInt(), parts[1].toInt(), base64Decode(bits.toByteArray()))
}
}
```
Relays MUST check if the authed user is in the filter before returning the event.
### Test cases
The filter below has 100 bits, with 10 rounds or hashes that should be able to match 10,000,000 keys without a single false positive.
```json
["prp", "100:10:QGKCgBEBAAhIAApO"]
```
It includes keys `ca29c211f1c72d5b6622268ff43d2288ea2b2cb5b9aa196ff9f1704fc914b71b` and `460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c`