12<html lang="en">3<head>4<meta charset="utf-8">5<meta name="viewport" content="width=device-width, initial-scale=1">6<title>NIP-45 - Event Counts — Nostr Instruction Manual</title>7<meta name="description" content="NIP-45: the COUNT verb. Relays count events server-side, return exact or approximate totals, and share HyperLogLog registers for mergeable counts.">8<link rel="preload" href="../assets/fonts/michroma-400-latin.woff2" as="font" type="font/woff2" crossorigin>9<link rel="preload" href="../assets/fonts/exo2-var-latin.woff2" as="font" type="font/woff2" crossorigin>10<link rel="preload" href="../assets/fonts/sairacondensed-600-latin.woff2" as="font" type="font/woff2" crossorigin>11<link rel="preload" href="../assets/fonts/sairacondensed-700-latin.woff2" as="font" type="font/woff2" crossorigin>12<link rel="preload" href="../assets/fonts/sairacondensed-500-latin.woff2" as="font" type="font/woff2" crossorigin>13<link rel="preload" href="../assets/fonts/sharetechmono-400-latin.woff2" as="font" type="font/woff2" crossorigin>14<link rel="preload" href="../assets/fonts/exo2-400i-latin.woff2" as="font" type="font/woff2" crossorigin>15<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml">16<link rel="stylesheet" href="../assets/manual.css">17</head>18<body>1920<svg width="0" height="0" style="position:absolute">21 <defs>22 <marker id="arr" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">23 <path d="M1,1 L8,4.5 L1,8 Z" fill="#f26a00"/>24 </marker>25 <marker id="arrb" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto">26 <path d="M1,1 L8,4.5 L1,8 Z" fill="#2e5f9e"/>27 </marker>28 </defs>29</svg>3031<div class="page">32 <span class="staple s1"></span><span class="staple s2"></span>3334 <header class="band">35 <a class="logo" href="../index.html">NOSTR<b>▸</b>PROTOCOL MANUAL</a>36 <span class="booklet-note">Chapter 45 - Relay Ops</span>37 </header>38 <nav class="tabs">39 <a href="../index.html">Contents</a>40 <a href="#overview" class="on">Overview</a>41 <a href="#spec">Spec</a>42 <a href="#examples">Examples</a>43 <a href="#history">History</a>44 </nav>4546 <div class="chapter">47 <div class="nipno" data-n="45">45</div>48 <div class="titles">49 <div class="kicker">Nostr Implementation Possibility - Hex № 45</div>50 <h1>Event Counts</h1>51 <p class="sub">Ask a relay how many events match a filter. Get a number back, not ten thousand events.</p>52 </div>53 </div>5455 <main class="spread">56 <div class="main">5758 <h2 class="bar" id="overview"><span class="num">1</span> Overview</h2>59 <p>Some numbers are expensive to compute on the client. To show a follower count, a client must download every kind-3 follow list that references a pubkey. Then it counts them and throws them away. That wastes bandwidth on both sides.</p>60 <p>Clients can cache the result. A separate indexing server can also cache it. Both options erode the decentralization of the network. They create a second-layer protocol on top of Nostr.</p>61 <p>This NIP moves the counting to the relay. A relay may support the verb <strong>COUNT</strong>. The client sends a query id and one or more <a href="01.html">NIP-01</a> filters. The relay answers with a single integer. An optional HyperLogLog extension lets clients merge counts from many relays into one estimate.</p>6263 <div class="box hint">64 <span class="tag">Hint!</span>65 <p>COUNT is optional relay hardware. Probe before you rely on it. If a relay does not implement the verb, expect a <code>NOTICE</code> or silence, and fall back to counting raw events yourself.</p>66 </div>6768 <figure class="diagram">69 <div class="frame">70 <svg viewBox="0 0 560 210" role="img" aria-label="Sequence diagram: client sends COUNT with a query id and filters, relay replies with a single COUNT result or a CLOSED refusal">71 <line class="d-wire" x1="110" y1="40" x2="110" y2="195" stroke-dasharray="3 4"/>72 <line class="d-wire" x1="450" y1="40" x2="450" y2="195" stroke-dasharray="3 4"/>73 <rect class="d-actor" x="55" y="8" width="110" height="30" rx="6"/>74 <text class="d-actor-label" x="110" y="28" text-anchor="middle">Client</text>75 <rect class="d-actor" x="395" y="8" width="110" height="30" rx="6"/>76 <text class="d-actor-label" x="450" y="28" text-anchor="middle">Relay</text>77 <path class="d-msg d-flow" d="M110,66 L445,66"/>78 <text class="d-label" x="280" y="59" text-anchor="middle">["COUNT", "q1", {"kinds":[3],"#p":["…"]}]</text>79 <path class="d-msg blue d-flow" d="M450,110 L115,110"/>80 <text class="d-label" x="280" y="103" text-anchor="middle">["COUNT", "q1", {"count":16578}]</text>81 <path class="d-msg blue" d="M450,160 L115,160"/>82 <text class="d-label" x="280" y="153" text-anchor="middle">["CLOSED", "q2", "auth-required: …"] on refusal</text>83 <circle r="4" fill="#f26a00">84 <animateMotion dur="2.6s" repeatCount="indefinite" path="M110,66 L445,66"/>85 </circle>86 <circle r="4" fill="#2e5f9e">87 <animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite" path="M450,110 L115,110"/>88 </circle>89 </svg>90 </div>91 <figcaption>Fig. 45-1 — <b>The COUNT round trip.</b> One request, one number back. A refusal comes as <code>CLOSED</code>.</figcaption>92 </figure>9394 <h2 class="bar" id="spec"><span class="num">2</span> The COUNT Verb</h2>95 <p>The client sends a <code>COUNT</code> message. It carries a query id and one or more filters. The filters follow the same rules as filters for the <a href="01.html">NIP-01</a> verb <code>REQ</code>. Multiple filters are OR'd together. The relay aggregates all matches into a single count result.</p>9697 <div class="crt">98 <div class="titlebar">Wire format - COUNT request</div>99<pre>[<span class="s">"COUNT"</span>, <span class="c"><query_id></span>, <span class="c"><filters JSON></span>...]</pre>100 </div>101102 <p>The relay answers with a <code>COUNT</code> response on the same query id. The payload is a JSON object with a <code>count</code> key. A relay may use probabilistic counting to reduce compute cost. If it does, it may set the <code>approximate</code> key in the response.</p>103104 <div class="crt">105 <div class="titlebar">Wire format - COUNT response</div>106<pre>[<span class="s">"COUNT"</span>, <span class="c"><query_id></span>, {<span class="k">"count"</span>: <span class="c"><integer></span>}]107108<span class="c">-- with optional flags --</span>109[<span class="s">"COUNT"</span>, <span class="c"><query_id></span>, {<span class="k">"count"</span>: <span class="c"><integer></span>, <span class="k">"approximate"</span>: <span class="c"><true|false></span>}]110[<span class="s">"COUNT"</span>, <span class="c"><query_id></span>, {<span class="k">"count"</span>: <span class="c"><integer></span>, <span class="k">"hll"</span>: <span class="s">"<hex>"</span>}]</pre>111 </div>112113 <div class="tscroll"><table class="ref">114 <caption>COUNT response payload</caption>115 <tr><th>Key</th><th>Type</th><th>Rule</th></tr>116 <tr><td class="btn">count</td><td>integer</td><td>The number of events that match the OR'd filters. Required.</td></tr>117 <tr><td class="btn">approximate</td><td>boolean</td><td>Optional. May be set when the relay used probabilistic counting.</td></tr>118 <tr><td class="btn">hll</td><td>hex string, 512 chars</td><td>Optional. HyperLogLog registers for this count. See §3.</td></tr>119 </table></div>120121 <p>A relay can refuse to fulfill a <code>COUNT</code> request. Whenever it refuses, it must return a <code>CLOSED</code> message for that query id. The <code>CLOSED</code> shape and its status prefixes come from <a href="01.html">NIP-01</a>. A relay that requires login first uses the <code>auth-required</code> prefix from <a href="42.html">NIP-42</a>.</p>122123 <div class="box tech">124 <span class="tag">Tech Note</span>125 <p>The source spec is inconsistent about the second element's name. The general sections call it <code><query_id></code>; the HyperLogLog sections and two examples still call it <code><subscription_id></code>. A 2025 change renamed it to "query id" because COUNT is not a subscription, but the rename missed the HLL sections. Both names denote the same field.</p>126 </div>127128 <h2 class="bar" id="hll"><span class="num">3</span> HyperLogLog</h2>129 <p>A count from one relay is a local truth. Users read from many relays, and the same reaction can sit on several of them. Plain integers from different relays cannot be merged without double counting.</p>130 <p><strong>HyperLogLog</strong> (HLL) fixes this. It is a probabilistic sketch: a small fixed-size register array that estimates the number of distinct items. A relay may return an HLL value together with the count, hex-encoded, in the <code>hll</code> key. Clients merge the HLL values from multiple relays and get one reasonable estimate for reaction counts, comment counts, and follower counts. This saves many millions of bytes of bandwidth for everybody.</p>131132 <h3>Relay-side algorithm</h3>133 <p>This is the only part needed for interoperability. Follow these steps to build the HLL value for a filter:</p>134 <ol>135 <li>Receive the filter. Check that it is eligible for HLL (see the offset rules below). Compute the deterministic <code>offset</code> for the filter.</li>136 <li>Initialize 256 registers to <code>0</code>.</li>137 <li>For every event that the filter counts, do this:138 <ol>139 <li>Read the byte at position <code>offset</code> of the event <code>pubkey</code>. That byte value is the register index <code>ri</code>.</li>140 <li>Count the leading zero bits starting at position <code>offset+1</code> of the event <code>pubkey</code>. Add <code>1</code>.</li>141 <li>Compare the result with the value stored at register <code>ri</code>. If the new number is bigger, store it.</li>142 </ol>143 </li>144 </ol>145 <p>On the client side, merging is simple. Walk through all 256 registers of each HLL value from each relay. Keep the highest value for each register, regardless of the relay. Then estimate the absolute count from the merged registers.</p>146147 <figure class="diagram">148 <div class="frame">149 <svg viewBox="0 0 560 200" role="img" aria-label="Two relays each send 256 HLL registers; the client merges them by taking the maximum per register and estimates one count">150 <rect class="d-actor" x="10" y="20" width="110" height="44" rx="8"/>151 <text class="d-actor-label" x="65" y="41" text-anchor="middle">Relay B</text>152 <text class="d-note" x="65" y="57" text-anchor="middle">hll: 06 07 07 05 …</text>153 <rect class="d-actor" x="10" y="126" width="110" height="44" rx="8"/>154 <text class="d-actor-label" x="65" y="147" text-anchor="middle">Relay C</text>155 <text class="d-note" x="65" y="163" text-anchor="middle">hll: 01 ef 07 05 …</text>156 <rect class="d-actor" x="225" y="72" width="130" height="50" rx="8"/>157 <text class="d-actor-label" x="290" y="93" text-anchor="middle">Merge</text>158 <text class="d-note" x="290" y="110" text-anchor="middle">max per register</text>159 <rect class="d-actor" x="430" y="72" width="120" height="50" rx="8"/>160 <text class="d-actor-label" x="490" y="93" text-anchor="middle">Estimate</text>161 <text class="d-note" x="490" y="110" text-anchor="middle">count ≈ 16578</text>162 <path class="d-msg blue d-flow" d="M122,44 C170,52 180,76 223,86"/>163 <path class="d-msg blue d-flow" d="M122,146 C170,138 180,114 223,106"/>164 <path class="d-msg d-flow" d="M357,97 L427,97"/>165 <text class="d-label" x="165" y="52" text-anchor="middle">COUNT</text>166 <text class="d-label" x="392" y="88" text-anchor="middle">256 regs</text>167 <circle r="4" fill="#2e5f9e">168 <animateMotion dur="2.6s" repeatCount="indefinite" path="M122,44 C170,52 180,76 223,86"/>169 </circle>170 <circle r="4" fill="#f26a00">171 <animateMotion dur="2.6s" begin="1.3s" repeatCount="indefinite" path="M357,97 L427,97"/>172 </circle>173 </svg>174 </div>175 <figcaption>Fig. 45-2 — <b>Mergeable counts.</b> Register-wise maximum joins sketches from many relays without double counting.</figcaption>176 </figure>177178 <h3>Computing the offset</h3>179 <p>The <code>offset</code> used above is derived deterministically from the filter that the client sent. Compute it like this:</p>180 <ol>181 <li>Take the first tag attribute in the filter. Tag attributes carry the <code>#</code> prefix, for example <code>#p</code>.</li>182 <li>From that attribute, take its first item. It is a string.</li>183 <li>Obtain a 32-byte hex string from it:184 <ul>185 <li>If the string is an event id or a pubkey in hex, use it as it is.</li>186 <li>If the string is an address (<code><kind>:<pubkey>:<d-tag></code>), use the <code><pubkey></code> part.</li>187 <li>If the string is anything else, hash it with <code>sha256()</code>. Take the result as a hex string.</li>188 </ul>189 </li>190 <li>From that 64-character hex string, take the character at position <code>32</code>.</li>191 <li>Read that character as a base-16 number.</li>192 <li>Add <code>8</code> to it. The result is the <code>offset</code>.</li>193 </ol>194 <p>For cases not covered above, such as filters without any tag attribute, behavior is not yet defined. This NIP may be modified later to specify those cases. For now no use case justifies HLL there.</p>195196 <figure class="diagram">197 <div class="frame">198 <svg viewBox="0 0 560 120" role="img" aria-label="Offset pipeline: first hash-tag attribute, first item, normalize to 32-byte hex, take hex character 32, parse base 16, add 8">199 <rect class="d-actor" x="10" y="35" width="100" height="50" rx="8"/>200 <text class="d-actor-label" x="60" y="57" text-anchor="middle">Filter</text>201 <text class="d-note" x="60" y="74" text-anchor="middle">first #tag item</text>202 <rect class="d-actor" x="155" y="35" width="120" height="50" rx="8"/>203 <text class="d-actor-label" x="215" y="57" text-anchor="middle">Normalize</text>204 <text class="d-note" x="215" y="74" text-anchor="middle">32-byte hex</text>205 <rect class="d-actor" x="320" y="35" width="120" height="50" rx="8"/>206 <text class="d-actor-label" x="380" y="57" text-anchor="middle">Char [32]</text>207 <text class="d-note" x="380" y="74" text-anchor="middle">base-16 digit</text>208 <rect class="d-actor" x="485" y="35" width="65" height="50" rx="8"/>209 <text class="d-actor-label" x="517" y="57" text-anchor="middle">+ 8</text>210 <text class="d-note" x="517" y="74" text-anchor="middle">= offset</text>211 <path class="d-msg d-flow" d="M112,60 L152,60"/>212 <path class="d-msg d-flow" d="M277,60 L317,60"/>213 <path class="d-msg d-flow" d="M442,60 L482,60"/>214 </svg>215 </div>216 <figcaption>Fig. 45-3 — <b>Offset pipeline.</b> The offset lands between 8 and 23, always inside the 32-byte pubkey.</figcaption>217 </figure>218219 <p><strong>Rationale.</strong> The <code>offset</code> must be deterministic. That is the only way a relay can cache HLL values instead of counting thousands of database rows on every query. It also lets a relay precompute HLL values for any target <code><id></code> or <code><pubkey></code> without storing the events themselves. That is handy for reactions, for example.</p>220221 <h3>Common filters</h3>222 <p>Some relays cache or precompute HLL values only for common canonical queries. They may refuse to count anything else. Each query below uses exactly one tag attribute with a single item, so implementors do not need to check attribute order. This list can grow later if more common useful queries appear:</p>223 <div class="tscroll"><table class="ref">224 <caption>Canonical HLL-eligible queries</caption>225 <tr><th>Counts</th><th>Filter</th><th>Kind source</th></tr>226 <tr><td class="btn">reactions</td><td><code>{"#e": ["<id>"], "kinds": [7]}</code></td><td><a href="25.html">NIP-25</a></td></tr>227 <tr><td class="btn">reposts</td><td><code>{"#e": ["<id>"], "kinds": [6]}</code></td><td><a href="18.html">NIP-18</a></td></tr>228 <tr><td class="btn">quotes</td><td><code>{"#q": ["<id>"], "kinds": [1, 1111]}</code></td><td><a href="10.html">NIP-10</a>, <a href="22.html">NIP-22</a></td></tr>229 <tr><td class="btn">replies</td><td><code>{"#e": ["<id>"], "kinds": [1]}</code></td><td><a href="10.html">NIP-10</a></td></tr>230 <tr><td class="btn">comments</td><td><code>{"#E": ["<id>"], "kinds": [1111]}</code></td><td><a href="22.html">NIP-22</a></td></tr>231 <tr><td class="btn">followers</td><td><code>{"#p": ["<pubkey>"], "kinds": [3]}</code></td><td><a href="02.html">NIP-02</a></td></tr>232 </table></div>233234 <h3>The hll encoding</h3>235 <p>The <code>hll</code> value is the concatenation of the 256 registers. Each register is one <code>uint8</code> byte. Therefore <code>hll</code> is always a 512-character hex string.</p>236237 <div class="box warn">238 <span class="tag">Warning!</span>239 <p><strong>Attack vector:</strong> an attacker can mine a pubkey with many zero bits exactly where the HLL algorithm looks. One reaction from that pubkey then "counts more" than others. The attacker needs a fresh mined pubkey per target, which is close to plain sybil spam anyway. The fix is the same for both attacks: do not fetch counts from open relays that accept everything. Base counts on relays that filter, so mostly real humans publish there, not bots or artificially generated pubkeys.</p>240 </div>241242 <h3>Client-side usage</h3>243 <p>Clients can combine HLL responses from relays with HLL sketches computed locally from raw events. Keep a local HLL per counter. Add every incoming source to it. An example flow for tracking reactions to an event Z over time:</p>244 <ol>245 <li>The client reads reactions from relays A, B, and C — the <a href="65.html">NIP-65</a> "read" relays of Z's author.</li>246 <li>Only B and C support HLL responses. The client fetches both and merges them locally.</li>247 <li>The client fetches all raw reaction events from A. It applies each event to the merged HLL with the same relay-side algorithm.</li>248 <li>The client reads the estimated count from the HLL and displays it to the user.</li>249 <li>Optionally, the client stores the HLL value together with a last-read date for relay A. On the next refresh it fetches only the new reactions from A, applies them, redownloads the HLL values from B and C, and reapplies those.</li>250 </ol>251 <p>This procedure lets the client download much less data.</p>252253 <div class="box tech">254 <span class="tag">Tech Note</span>255 <p>The estimation step is deliberately unspecified. The source spec points to implementation code instead of a formula and allows different estimators "with different quirks". Two conforming clients can therefore show slightly different numbers from identical registers. The zero-bit count in step 3.2 also has no stated cap, though 256 registers with uint8 values implies one.</p>256 </div>257258 <h2 class="bar" id="examples"><span class="num">4</span> Worked Examples</h2>259 <p>The session below shows every response shape. Orange lines go to the relay. Blue lines come from the relay. The 512-character <code>hll</code> strings are shortened here; a real one is never truncated.</p>260 <div class="crt">261 <div class="titlebar">Session transcript - wss://relay.example.com</div>262<pre><span class="c">-- count notes and reactions by one author --</span>263<span class="send">→ ["COUNT", "q1", {"kinds": [1, 7], "authors": ["22a12a12…"]}]</span>264<span class="recv">← ["COUNT", "q1", {"count": 5}]</span>265266<span class="c">-- count all notes, relay answers probabilistically --</span>267<span class="send">→ ["COUNT", "q2", {"kinds": [1]}]</span>268<span class="recv">← ["COUNT", "q2", {"count": 93412452, "approximate": true}]</span>269270<span class="c">-- follower count with HyperLogLog --</span>271<span class="send">→ ["COUNT", "q3", {"kinds": [3], "#p": ["f7234bd4…"]}]</span>272<span class="recv">← ["COUNT", "q3", {"count": 16578, "hll": "0607070505060806…0405070708"}]</span>273274<span class="c">-- reaction count with HyperLogLog --</span>275<span class="send">→ ["COUNT", "q4", {"kinds": [7], "#e": ["5c83da77…"]}]</span>276<span class="recv">← ["COUNT", "q4", {"count": 2044, "hll": "01ef070505060806…0405070708"}]</span>277278<span class="c">-- relay refuses to count gift wraps --</span>279<span class="send">→ ["COUNT", "q5", {"kinds": [1059], "#p": ["f7234bd4…"]}]</span>280<span class="recv">← ["CLOSED", "q5", "auth-required: cannot count other people's DMs"]</span></pre>281 </div>282 <p>In the last exchange the relay protects kind-1059 gift wraps (<a href="59.html">NIP-59</a>). It demands <a href="42.html">NIP-42</a> authentication before it counts private messages.</p>283284 <h2 class="bar" id="history"><span class="num">5</span> Version History</h2>285 <p>NIP-45 has lived through a deprecation and a resurrection. Notable changes, newest first:</p>286 <ul class="patchnotes">287 <li><span class="ver">2026</span><span class="when">2026-02</span>Added the HyperLogLog extension: <code>hll</code> responses, the register algorithm, the offset formula, canonical queries, and the mined-pubkey attack note.</li>288 <li><span class="ver">2025</span><span class="when">2025-10</span>Renamed the subscription id to a query id. COUNT is a one-shot query, not a subscription.</li>289 <li><span class="ver">2024</span><span class="when">2024-07</span>Restored. The earlier removal was reverted and COUNT returned to the spec.</li>290 <li><span class="ver">2023</span><span class="when">2023-12</span>Refusals standardized: a relay that declines a COUNT must reply with <code>CLOSED</code>.</li>291 <li><span class="ver">2023</span><span class="when">2023-10</span>Deprecated and slated for removal, before the 2024 revert brought it back.</li>292 <li><span class="ver">2023</span><span class="when">2023-08</span>Added the <code>approximate</code> key so relays can flag probabilistic counts.</li>293 <li><span class="ver">2023</span><span class="when">2023-05</span>Clarified multi-filter behavior: filters are OR'd and aggregated into one count.</li>294 <li class="minor"><span class="ver">2023</span><span class="when">2023-04</span>Counting by arbitrary filters spelled out; grammar and formatting fixes.</li>295 <li><span class="ver">Origin</span><span class="when">2023-01</span>Jonathan Staab added NIP-45, defining the COUNT verb.</li>296 </ul>297298 <div class="credits">299 <h3 class="cardhead">Original Proposal - Credits</h3>300 <table>301 <tr><td>Author</td><td>Jonathan Staab (hodlbod)</td></tr>302 <tr><td>First commit</td><td>2023-01-03 — “Add NIP-45, which defines a COUNT verb”</td></tr>303 <tr><td>Status</td><td>draft - optional - relay feature</td></tr>304 <tr><td>Source</td><td><a href="https://github.com/nostr-protocol/nips/blob/master/45.md">45.md on GitHub</a> - <a href="https://github.com/nostr-protocol/nips/commits/master/45.md">full change history</a></td></tr>305 </table>306 </div>307308 <h2 class="bar"><span class="num">6</span> See Also</h2>309 <ul>310 <li><a href="01.html">NIP-01</a> — defines the filters that COUNT reuses, and the <code>CLOSED</code> message for refusals.</li>311 <li><a href="42.html">NIP-42</a> — client authentication; source of the <code>auth-required</code> refusal prefix.</li>312 <li><a href="02.html">NIP-02</a> — kind-3 follow lists, the raw material for follower counts.</li>313 <li><a href="25.html">NIP-25</a> — kind-7 reactions, the most counted event kind.</li>314 <li><a href="18.html">NIP-18</a> — kind-6 reposts and quote conventions.</li>315 <li><a href="22.html">NIP-22</a> — kind-1111 comments counted by the comment and quote queries.</li>316 <li><a href="65.html">NIP-65</a> — relay lists that tell a client where to count from.</li>317 </ul>318 </div>319320 <aside>321 <div class="cartridge">322 <div class="inner">323 <h3 class="cardhead">Spec Card</h3>324 <div class="lights"><span class="led on"></span><span class="led warn"></span><span class="led warn"></span></div>325 <dl>326 <dt>Status</dt><dd><span class="chip draft">draft</span><span class="chip">optional</span><span class="chip">relay</span></dd>327 <dt>Defines</dt><dd>COUNT verb - count/approximate/hll response keys</dd>328 <dt>Kinds</dt><dd>none — counts existing kinds</dd>329 <dt>Requires</dt><dd><a href="01.html">NIP-01</a> filters and CLOSED</dd>330 <dt>Transport</dt><dd>WebSocket - JSON arrays</dd>331 <dt>Crypto</dt><dd>sha256 (offset derivation only)</dd>332 <dt>First commit</dt><dd>2023-01-03</dd>333 <dt>Last updated</dt><dd>2026-02-06</dd>334 </dl>335 </div>336 </div>337 </aside>338 </main>339340 <nav class="navbtns">341 <a href="44.html">◀ NIP-44: Encrypted Payloads (Versioned)</a>342 <a href="46.html">NIP-46: Nostr Remote Signing ▶</a>343 </nav>344345 <footer class="pagefoot">346 <a href="../index.html">Nostr Protocol Manual</a>347 <span class="pageno">NIP 45 / F4</span>348 </footer>349</div>350351<script src="../assets/webmcp.js" defer></script>352</body>353</html>