2.3 KiB
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 with an rp
or prp
require AUTH to be downloaded.
Read Permission
The rp
tag accepts a list of pubkeys
["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:
- the size of the bit array
- the number of hashing rounds used by the filter
- the bit array in Base64.
["prp", "<BitArray Size>:<Rounds>:<base64>"]
Bloom filters MUST use SHA-256
functions of the key + iterating index as the pseudocode below:
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() {
return size + ":" + rounds + ":" + base64Encode(bits.toByteArray())
}
fun decode(str: String): BloomFilter {
val parts = str.split(":")
return BloomFilter(parts[0].toInt(), parts[1].toInt(), base64Decode(parts[2]))
}
}
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 of hashes that should be able to match 10,000,000 keys without a single false positive.
["prp", "100:10:QGKCgBEBAAhIAApO"]
It includes keys ca29c211f1c72d5b6622268ff43d2288ea2b2cb5b9aa196ff9f1704fc914b71b
and 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c