diff --git a/17.md b/17.md index 74fe2c7a..73e61f72 100644 --- a/17.md +++ b/17.md @@ -104,14 +104,61 @@ Clients SHOULD publish kind `14` events to the `10050`-listed relays. If that is A client MAY publish a kind `30010` which means saw messages with a `"d"` tag set to receivers pubkey. -The `.content` field is a base64 encoded string of a bloom filter containing message ids (gift wrapped) saw by receiver. +The `.content` field has 4 sections separated by `:`: + +1. The number of bits in the bit array, +2. The number of hash rounds applied. +3. The Base64 encoded string of a bloom filter containing message ids (gift wrapped) saw by receiver. +4. The salt encoded in the Base64. The sender pubkey's client MAY query that specific event to check which messaged in this chat is seen by receiver to enhance user experience. +Bloom filters MUST use `SHA256` functions applied to the concatenation of the key, salt, and index, as demonstrated in the pseudocode below: + +```js +class BloomFilter(size: Int, rounds: Int, buffer: ByteArray, salt: ByteArray) { + val bits = BitArray(buffer) + + fun bitIndex(value: ByteArray, index: Byte) { + return BigInt(sha256(value || salt || index)) % size + } + + fun add(id: HexID) { + val value = id.hexToByteArray() + + for (index in 0 until rounds) { + bits[bitIndex(value, index)] = true + } + } + + fun mightContains(id: HexID): Boolean { + val value = id.hexToByteArray() + + for (index in 0 until rounds) { + if (!bits[bitIndex(value, index)]) { + return false + } + } + + return true + } + + fun encode() { + return size + ":" + rounds + ":" + base64Encode(bits.toByteArray()) + ":" + base64Encode(salt) + } + + fun decode(str: String): BloomFilter { + val [sizeStr, roundsStr, bufferB64, saltB64] = str.split(":") + return BloomFilter(sizeStr.toInt(), roundsStr.toInt(), base64Decode(bufferB64), base64Decode(saltB64)) + } +} +``` + Example event: ```json { + "pubkey" : "badbdda507572b397852048ea74f2ef3ad92b1aac07c3d4e1dec174e8cdc962a", "kind": 30010, "created_at": 1738964056, "tags": [ @@ -120,10 +167,12 @@ Example event: "bd4ae3e67e29964d494172261dc45395c89f6bd2e774642e366127171dfb81f5" ] ], - "content": "AAAAAAAACJEAAAAAAAAAAQAAAAAAAAiRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "content": "100:10:AAAkAQANcYQFCQoB:hZkZYqqdxcE", } ``` +In this example the pubkey `badbdda507572b397852048ea74f2ef3ad92b1aac07c3d4e1dec174e8cdc962a`, has confirmed that they saw the messages with ids of `ca29c211f1c72d5b6622268ff43d2288ea2b2cb5b9aa196ff9f1704fc914b71b` and `460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c` from pubkey `bd4ae3e67e29964d494172261dc45395c89f6bd2e774642e366127171dfb81f5`. + A client MAY encrypt the `.content` based on [NIP-44](44.md) for more privacy. ## Relays