nips/76.md
Vitor Pamplona c1649e45b8
typos
2024-09-13 13:00:40 -04:00

2.2 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

Bloom filters are bit arrays that encode keys n times. They are represented by a base64 encoded tag value with the n as the third element.

["prp", "<bit size>:<rounds>:<base64>"]

Bloom filters MUST use SHA-256 functions of the key + iterating index as the pseudocode below:

class BloomFilter(size: Int, n: 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..n) {
            bits[bitIndex(value, index)] = true 
        }
    }

    fun mightContains(pubkey: HexKey): Boolean {
        val value = pubkey.hexToByteArray()

        for (index in 0..n) {
            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 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