summaryrefslogtreecommitdiffstats
path: root/benchmarks
diff options
context:
space:
mode:
Diffstat (limited to 'benchmarks')
-rw-r--r--benchmarks/comparison/README.md44
-rw-r--r--benchmarks/comparison/comparison_bench_test.go510
-rw-r--r--benchmarks/comparison/go.mod39
-rw-r--r--benchmarks/comparison/go.sum85
4 files changed, 678 insertions, 0 deletions
diff --git a/benchmarks/comparison/README.md b/benchmarks/comparison/README.md
new file mode 100644
index 0000000..1b97429
--- /dev/null
+++ b/benchmarks/comparison/README.md
@@ -0,0 +1,44 @@
1# Nostr Library Comparison Benchmarks
2
3This module contains benchmarks comparing `code.northwest.io/nostr` with other popular Go Nostr libraries:
4
5- **NWIO** (`code.northwest.io/nostr`) - This library
6- **NBD** (`github.com/nbd-wtf/go-nostr`) - Popular community library
7- **Fiat** (`fiatjaf.com/nostr`) - Original implementation by Fiatjaf
8
9## Why a Separate Module?
10
11The comparison libraries are isolated in this separate Go module to keep the main `code.northwest.io/nostr` package clean. Users who import the main package won't have `fiatjaf.com/nostr` or `github.com/nbd-wtf/go-nostr` pulled into their dependency tree.
12
13## Running Benchmarks
14
15From this directory:
16
17```bash
18# Run all comparison benchmarks
19go test -bench=. -benchmem
20
21# Run specific benchmarks
22go test -bench=BenchmarkEventSign -benchmem
23
24# Compare NWIO vs NBD
25go test -bench='.*_(NWIO|NBD)' -benchmem
26```
27
28From the project root:
29
30```bash
31cd benchmarks/comparison
32go test -bench=. -benchmem
33```
34
35## Benchmark Categories
36
37- **Event Unmarshaling/Marshaling**: JSON parsing and serialization
38- **Event Serialization**: Canonical serialization for ID computation
39- **Event ID Computation**: Computing event ID hashes
40- **Key Generation**: Generating new private keys
41- **Event Signing/Verification**: Cryptographic operations
42- **Filter Matching**: Simple and complex filter matching
43
44See [../../BENCHMARKS.md](../../BENCHMARKS.md) for detailed documentation.
diff --git a/benchmarks/comparison/comparison_bench_test.go b/benchmarks/comparison/comparison_bench_test.go
new file mode 100644
index 0000000..866b4df
--- /dev/null
+++ b/benchmarks/comparison/comparison_bench_test.go
@@ -0,0 +1,510 @@
1package comparison_test
2
3import (
4 "encoding/hex"
5 "encoding/json"
6 "testing"
7
8 nwio "code.northwest.io/nostr"
9 nbd "github.com/nbd-wtf/go-nostr"
10 fiat "fiatjaf.com/nostr"
11)
12
13// Sample event data for benchmarks
14var (
15 samplePubKey = "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"
16 sampleSig = "230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2b0d0e1b8f1e6e7c4e1c6e8e3e9e8e3e9e8"
17 sampleID = "d42c96ccac39e0113b2ef8df82e82e2e15e0e1e7e9e5e7e1e7e9e5e7e1e7e9e5"
18
19 sampleEventJSON = `{
20 "id": "d42c96ccac39e0113b2ef8df82e82e2e15e0e1e7e9e5e7e1e7e9e5e7e1e7e9e5",
21 "pubkey": "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d",
22 "created_at": 1672531200,
23 "kind": 1,
24 "tags": [["e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://nostr.example.com"]],
25 "content": "Hello Nostr!",
26 "sig": "230e9d8f0ddaf7eb70b5f7741ccfa37e87a455c9a469282e3464e2052d3192cd63a167e196e381ef9d7e69e9ea43af2b0d0e1b8f1e6e7c4e1c6e8e3e9e8e3e9e8"
27 }`
28)
29
30// ============================================================================
31// Event Unmarshaling Benchmarks
32// ============================================================================
33
34func BenchmarkEventUnmarshal_NWIO(b *testing.B) {
35 data := []byte(sampleEventJSON)
36 b.ResetTimer()
37 for i := 0; i < b.N; i++ {
38 var evt nwio.Event
39 if err := json.Unmarshal(data, &evt); err != nil {
40 b.Fatal(err)
41 }
42 }
43}
44
45func BenchmarkEventUnmarshal_NBD(b *testing.B) {
46 data := []byte(sampleEventJSON)
47 b.ResetTimer()
48 for i := 0; i < b.N; i++ {
49 var evt nbd.Event
50 if err := json.Unmarshal(data, &evt); err != nil {
51 b.Fatal(err)
52 }
53 }
54}
55
56func BenchmarkEventUnmarshal_Fiat(b *testing.B) {
57 data := []byte(sampleEventJSON)
58 b.ResetTimer()
59 for i := 0; i < b.N; i++ {
60 var evt fiat.Event
61 if err := json.Unmarshal(data, &evt); err != nil {
62 b.Fatal(err)
63 }
64 }
65}
66
67// ============================================================================
68// Event Marshaling Benchmarks
69// ============================================================================
70
71func BenchmarkEventMarshal_NWIO(b *testing.B) {
72 evt := &nwio.Event{
73 ID: sampleID,
74 PubKey: samplePubKey,
75 CreatedAt: 1672531200,
76 Kind: 1,
77 Tags: nwio.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
78 Content: "Hello Nostr!",
79 Sig: sampleSig,
80 }
81 b.ResetTimer()
82 for i := 0; i < b.N; i++ {
83 if _, err := json.Marshal(evt); err != nil {
84 b.Fatal(err)
85 }
86 }
87}
88
89func BenchmarkEventMarshal_NBD(b *testing.B) {
90 evt := &nbd.Event{
91 ID: sampleID,
92 PubKey: samplePubKey,
93 CreatedAt: nbd.Timestamp(1672531200),
94 Kind: 1,
95 Tags: nbd.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
96 Content: "Hello Nostr!",
97 Sig: sampleSig,
98 }
99 b.ResetTimer()
100 for i := 0; i < b.N; i++ {
101 if _, err := json.Marshal(evt); err != nil {
102 b.Fatal(err)
103 }
104 }
105}
106
107func BenchmarkEventMarshal_Fiat(b *testing.B) {
108 sig, _ := hex.DecodeString(sampleSig)
109 var sigBytes [64]byte
110 copy(sigBytes[:], sig)
111
112 pubkey, _ := fiat.PubKeyFromHex(samplePubKey)
113 id, _ := fiat.IDFromHex(sampleID)
114
115 evt := &fiat.Event{
116 ID: id,
117 PubKey: pubkey,
118 CreatedAt: fiat.Timestamp(1672531200),
119 Kind: 1,
120 Tags: fiat.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
121 Content: "Hello Nostr!",
122 Sig: sigBytes,
123 }
124 b.ResetTimer()
125 for i := 0; i < b.N; i++ {
126 if _, err := json.Marshal(evt); err != nil {
127 b.Fatal(err)
128 }
129 }
130}
131
132// ============================================================================
133// Event Serialization (for ID computation) Benchmarks
134// ============================================================================
135
136func BenchmarkEventSerialize_NWIO(b *testing.B) {
137 evt := &nwio.Event{
138 PubKey: samplePubKey,
139 CreatedAt: 1672531200,
140 Kind: 1,
141 Tags: nwio.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
142 Content: "Hello Nostr!",
143 }
144 b.ResetTimer()
145 for i := 0; i < b.N; i++ {
146 _ = evt.Serialize()
147 }
148}
149
150func BenchmarkEventSerialize_NBD(b *testing.B) {
151 evt := &nbd.Event{
152 PubKey: samplePubKey,
153 CreatedAt: nbd.Timestamp(1672531200),
154 Kind: 1,
155 Tags: nbd.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
156 Content: "Hello Nostr!",
157 }
158 b.ResetTimer()
159 for i := 0; i < b.N; i++ {
160 _ = evt.Serialize()
161 }
162}
163
164func BenchmarkEventSerialize_Fiat(b *testing.B) {
165 pubkey, _ := fiat.PubKeyFromHex(samplePubKey)
166 evt := &fiat.Event{
167 PubKey: pubkey,
168 CreatedAt: fiat.Timestamp(1672531200),
169 Kind: 1,
170 Tags: fiat.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
171 Content: "Hello Nostr!",
172 }
173 b.ResetTimer()
174 for i := 0; i < b.N; i++ {
175 _ = evt.Serialize()
176 }
177}
178
179// ============================================================================
180// Event ID Computation Benchmarks
181// ============================================================================
182
183func BenchmarkComputeID_NWIO(b *testing.B) {
184 evt := &nwio.Event{
185 PubKey: samplePubKey,
186 CreatedAt: 1672531200,
187 Kind: 1,
188 Tags: nwio.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
189 Content: "Hello Nostr!",
190 }
191 b.ResetTimer()
192 for i := 0; i < b.N; i++ {
193 _ = evt.ComputeID()
194 }
195}
196
197func BenchmarkComputeID_NBD(b *testing.B) {
198 evt := &nbd.Event{
199 PubKey: samplePubKey,
200 CreatedAt: nbd.Timestamp(1672531200),
201 Kind: 1,
202 Tags: nbd.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
203 Content: "Hello Nostr!",
204 }
205 b.ResetTimer()
206 for i := 0; i < b.N; i++ {
207 _ = evt.GetID()
208 }
209}
210
211func BenchmarkComputeID_Fiat(b *testing.B) {
212 pubkey, _ := fiat.PubKeyFromHex(samplePubKey)
213 evt := &fiat.Event{
214 PubKey: pubkey,
215 CreatedAt: fiat.Timestamp(1672531200),
216 Kind: 1,
217 Tags: fiat.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
218 Content: "Hello Nostr!",
219 }
220 b.ResetTimer()
221 for i := 0; i < b.N; i++ {
222 _ = evt.GetID()
223 }
224}
225
226// ============================================================================
227// Key Generation Benchmarks
228// ============================================================================
229
230func BenchmarkGenerateKey_NWIO(b *testing.B) {
231 for i := 0; i < b.N; i++ {
232 if _, err := nwio.GenerateKey(); err != nil {
233 b.Fatal(err)
234 }
235 }
236}
237
238func BenchmarkGenerateKey_NBD(b *testing.B) {
239 for i := 0; i < b.N; i++ {
240 _ = nbd.GeneratePrivateKey()
241 }
242}
243
244func BenchmarkGenerateKey_Fiat(b *testing.B) {
245 for i := 0; i < b.N; i++ {
246 _ = fiat.Generate()
247 }
248}
249
250// ============================================================================
251// Event Signing Benchmarks
252// ============================================================================
253
254func BenchmarkEventSign_NWIO(b *testing.B) {
255 key, err := nwio.GenerateKey()
256 if err != nil {
257 b.Fatal(err)
258 }
259 b.ResetTimer()
260
261 for i := 0; i < b.N; i++ {
262 evt := &nwio.Event{
263 CreatedAt: 1672531200,
264 Kind: 1,
265 Tags: nwio.Tags{},
266 Content: "Hello Nostr!",
267 }
268 if err := key.Sign(evt); err != nil {
269 b.Fatal(err)
270 }
271 }
272}
273
274func BenchmarkEventSign_NBD(b *testing.B) {
275 sk := nbd.GeneratePrivateKey()
276 b.ResetTimer()
277
278 for i := 0; i < b.N; i++ {
279 evt := &nbd.Event{
280 CreatedAt: nbd.Timestamp(1672531200),
281 Kind: 1,
282 Tags: nbd.Tags{},
283 Content: "Hello Nostr!",
284 }
285 if err := evt.Sign(sk); err != nil {
286 b.Fatal(err)
287 }
288 }
289}
290
291func BenchmarkEventSign_Fiat(b *testing.B) {
292 sk := fiat.Generate()
293 b.ResetTimer()
294
295 for i := 0; i < b.N; i++ {
296 evt := &fiat.Event{
297 CreatedAt: fiat.Timestamp(1672531200),
298 Kind: 1,
299 Tags: fiat.Tags{},
300 Content: "Hello Nostr!",
301 }
302 if err := evt.Sign(sk); err != nil {
303 b.Fatal(err)
304 }
305 }
306}
307
308// ============================================================================
309// Event Verification Benchmarks
310// ============================================================================
311
312func BenchmarkEventVerify_NWIO(b *testing.B) {
313 // Create and sign an event
314 key, _ := nwio.GenerateKey()
315 evt := &nwio.Event{
316 CreatedAt: 1672531200,
317 Kind: 1,
318 Tags: nwio.Tags{},
319 Content: "Hello Nostr!",
320 }
321 key.Sign(evt)
322
323 b.ResetTimer()
324 for i := 0; i < b.N; i++ {
325 if !evt.Verify() {
326 b.Fatal("verification failed")
327 }
328 }
329}
330
331func BenchmarkEventVerify_NBD(b *testing.B) {
332 // Create and sign an event
333 sk := nbd.GeneratePrivateKey()
334 evt := &nbd.Event{
335 CreatedAt: nbd.Timestamp(1672531200),
336 Kind: 1,
337 Tags: nbd.Tags{},
338 Content: "Hello Nostr!",
339 }
340 evt.Sign(sk)
341
342 b.ResetTimer()
343 for i := 0; i < b.N; i++ {
344 if ok, _ := evt.CheckSignature(); !ok {
345 b.Fatal("verification failed")
346 }
347 }
348}
349
350func BenchmarkEventVerify_Fiat(b *testing.B) {
351 // Create and sign an event
352 sk := fiat.Generate()
353 evt := &fiat.Event{
354 CreatedAt: fiat.Timestamp(1672531200),
355 Kind: 1,
356 Tags: fiat.Tags{},
357 Content: "Hello Nostr!",
358 }
359 evt.Sign(sk)
360
361 b.ResetTimer()
362 for i := 0; i < b.N; i++ {
363 if !evt.VerifySignature() {
364 b.Fatal("verification failed")
365 }
366 }
367}
368
369// ============================================================================
370// Filter Matching Benchmarks
371// ============================================================================
372
373func BenchmarkFilterMatch_NWIO(b *testing.B) {
374 filter := &nwio.Filter{
375 Kinds: []int{1},
376 Authors: []string{samplePubKey},
377 }
378 evt := &nwio.Event{
379 PubKey: samplePubKey,
380 CreatedAt: 1672531200,
381 Kind: 1,
382 Content: "Hello Nostr!",
383 }
384
385 b.ResetTimer()
386 for i := 0; i < b.N; i++ {
387 if !filter.Matches(evt) {
388 b.Fatal("filter should match")
389 }
390 }
391}
392
393func BenchmarkFilterMatch_NBD(b *testing.B) {
394 filter := nbd.Filter{
395 Kinds: []int{1},
396 Authors: []string{samplePubKey},
397 }
398 evt := &nbd.Event{
399 PubKey: samplePubKey,
400 CreatedAt: nbd.Timestamp(1672531200),
401 Kind: 1,
402 Content: "Hello Nostr!",
403 }
404
405 b.ResetTimer()
406 for i := 0; i < b.N; i++ {
407 if !filter.Matches(evt) {
408 b.Fatal("filter should match")
409 }
410 }
411}
412
413func BenchmarkFilterMatch_Fiat(b *testing.B) {
414 pubkey, _ := fiat.PubKeyFromHex(samplePubKey)
415 filter := fiat.Filter{
416 Kinds: []fiat.Kind{1},
417 Authors: []fiat.PubKey{pubkey},
418 }
419 evt := &fiat.Event{
420 PubKey: pubkey,
421 CreatedAt: fiat.Timestamp(1672531200),
422 Kind: 1,
423 Content: "Hello Nostr!",
424 }
425
426 b.ResetTimer()
427 for i := 0; i < b.N; i++ {
428 if !filter.Matches(*evt) {
429 b.Fatal("filter should match")
430 }
431 }
432}
433
434// ============================================================================
435// Complex Filter Matching Benchmarks (with tags)
436// ============================================================================
437
438func BenchmarkFilterMatchComplex_NWIO(b *testing.B) {
439 filter := &nwio.Filter{
440 Kinds: []int{1, 6, 7},
441 Authors: []string{samplePubKey[:8]}, // Prefix match
442 Tags: map[string][]string{
443 "e": {"5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"},
444 },
445 }
446 evt := &nwio.Event{
447 PubKey: samplePubKey,
448 CreatedAt: 1672531200,
449 Kind: 1,
450 Tags: nwio.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
451 Content: "Hello Nostr!",
452 }
453
454 b.ResetTimer()
455 for i := 0; i < b.N; i++ {
456 if !filter.Matches(evt) {
457 b.Fatal("filter should match")
458 }
459 }
460}
461
462func BenchmarkFilterMatchComplex_NBD(b *testing.B) {
463 filter := nbd.Filter{
464 Kinds: []int{1, 6, 7},
465 Authors: []string{samplePubKey}, // NBD also supports prefix, use full key for simplicity
466 Tags: nbd.TagMap{
467 "e": []string{"5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"},
468 },
469 }
470 evt := &nbd.Event{
471 PubKey: samplePubKey,
472 CreatedAt: nbd.Timestamp(1672531200),
473 Kind: 1,
474 Tags: nbd.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
475 Content: "Hello Nostr!",
476 }
477
478 b.ResetTimer()
479 for i := 0; i < b.N; i++ {
480 if !filter.Matches(evt) {
481 b.Fatal("filter should match")
482 }
483 }
484}
485
486func BenchmarkFilterMatchComplex_Fiat(b *testing.B) {
487 pubkey, _ := fiat.PubKeyFromHex(samplePubKey)
488
489 filter := fiat.Filter{
490 Kinds: []fiat.Kind{1, 6, 7},
491 Authors: []fiat.PubKey{pubkey}, // Use full pubkey for simplicity
492 Tags: fiat.TagMap{
493 "e": []string{"5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"},
494 },
495 }
496 evt := &fiat.Event{
497 PubKey: pubkey,
498 CreatedAt: fiat.Timestamp(1672531200),
499 Kind: 1,
500 Tags: fiat.Tags{{"e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36"}},
501 Content: "Hello Nostr!",
502 }
503
504 b.ResetTimer()
505 for i := 0; i < b.N; i++ {
506 if !filter.Matches(*evt) {
507 b.Fatal("filter should match")
508 }
509 }
510}
diff --git a/benchmarks/comparison/go.mod b/benchmarks/comparison/go.mod
new file mode 100644
index 0000000..f76c374
--- /dev/null
+++ b/benchmarks/comparison/go.mod
@@ -0,0 +1,39 @@
1module code.northwest.io/nostr/benchmarks/comparison
2
3go 1.25
4
5require (
6 code.northwest.io/nostr v0.0.0
7 fiatjaf.com/nostr v0.0.0-20260211144128-7a4b71b39b12
8 github.com/nbd-wtf/go-nostr v0.52.3
9)
10
11require (
12 github.com/ImVexed/fasturl v0.0.0-20230304231329-4e41488060f3 // indirect
13 github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
14 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect
15 github.com/bytedance/sonic v1.13.1 // indirect
16 github.com/bytedance/sonic/loader v0.2.4 // indirect
17 github.com/cloudwego/base64x v0.1.5 // indirect
18 github.com/coder/websocket v1.8.13 // indirect
19 github.com/decred/dcrd/crypto/blake256 v1.1.0 // indirect
20 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
21 github.com/josharian/intern v1.0.0 // indirect
22 github.com/json-iterator/go v1.1.12 // indirect
23 github.com/klauspost/cpuid/v2 v2.2.10 // indirect
24 github.com/mailru/easyjson v0.9.0 // indirect
25 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
26 github.com/modern-go/reflect2 v1.0.2 // indirect
27 github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
28 github.com/templexxx/cpu v0.0.1 // indirect
29 github.com/templexxx/xhex v0.0.0-20200614015412-aed53437177b // indirect
30 github.com/tidwall/gjson v1.18.0 // indirect
31 github.com/tidwall/match v1.1.1 // indirect
32 github.com/tidwall/pretty v1.2.1 // indirect
33 github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
34 golang.org/x/arch v0.15.0 // indirect
35 golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
36 golang.org/x/sys v0.35.0 // indirect
37)
38
39replace code.northwest.io/nostr => ../..
diff --git a/benchmarks/comparison/go.sum b/benchmarks/comparison/go.sum
new file mode 100644
index 0000000..fb3bb78
--- /dev/null
+++ b/benchmarks/comparison/go.sum
@@ -0,0 +1,85 @@
1fiatjaf.com/nostr v0.0.0-20260211144128-7a4b71b39b12 h1:lNVaw/O5ThXVzO0Pz7D+b9fys/OaVaDG3C10kCJQFvg=
2fiatjaf.com/nostr v0.0.0-20260211144128-7a4b71b39b12/go.mod h1:ue7yw0zHfZj23Ml2kVSdBx0ENEaZiuvGxs/8VEN93FU=
3github.com/ImVexed/fasturl v0.0.0-20230304231329-4e41488060f3 h1:ClzzXMDDuUbWfNNZqGeYq4PnYOlwlOVIvSyNaIy0ykg=
4github.com/ImVexed/fasturl v0.0.0-20230304231329-4e41488060f3/go.mod h1:we0YA5CsBbH5+/NUzC/AlMmxaDtWlXeNsqrwXjTzmzA=
5github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
6github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
7github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ=
8github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
9github.com/bytedance/sonic v1.13.1 h1:Jyd5CIvdFnkOWuKXr+wm4Nyk2h0yAFsr8ucJgEasO3g=
10github.com/bytedance/sonic v1.13.1/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
11github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
12github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
13github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
14github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
15github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
16github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
17github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=
18github.com/coder/websocket v1.8.13/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs=
19github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
20github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
21github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
22github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
23github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
24github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
25github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
26github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
27github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
28github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
29github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
30github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
31github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
32github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
33github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
34github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
35github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
36github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
37github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
38github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
39github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
40github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
41github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
42github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
43github.com/nbd-wtf/go-nostr v0.52.3 h1:Xd87pXfJEJRXHpM+fLjQQln8dBNNaoPA10V7BbyP4KI=
44github.com/nbd-wtf/go-nostr v0.52.3/go.mod h1:4avYoc9mDGZ9wHsvCOhHH9vPzKucCfuYBtJUSpHTfNk=
45github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
46github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
47github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
48github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
49github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
50github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
51github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
52github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
53github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
54github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
55github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
56github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
57github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
58github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
59github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
60github.com/templexxx/cpu v0.0.1 h1:hY4WdLOgKdc8y13EYklu9OUTXik80BkxHoWvTO6MQQY=
61github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
62github.com/templexxx/xhex v0.0.0-20200614015412-aed53437177b h1:XeDLE6c9mzHpdv3Wb1+pWBaWv/BlHK0ZYIu/KaL6eHg=
63github.com/templexxx/xhex v0.0.0-20200614015412-aed53437177b/go.mod h1:7rwmCH0wC2fQvNEvPZ3sKXukhyCTyiaZ5VTZMQYpZKQ=
64github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
65github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
66github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
67github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
68github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
69github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
70github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
71github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
72github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
73golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
74golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
75golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
76golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
77golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
78golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
79golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
80golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
81gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
82gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
83gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
84gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
85nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=