Skip to content

perf(relay): batch repeated-author Nostr signature verification - #3329

Draft
jmecom wants to merge 4 commits into
mainfrom
jm/batch-nostr-verification
Draft

jmecom wants to merge 4 commits into
mainfrom
jm/batch-nostr-verification

Conversation

@jmecom

@jmecom jmecom commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Desktop relay signature requests already arrive in groups, but previously verified each signature separately. Use BIP-340 batch verification for bounded groups with repeated authors, retaining libsecp256k1 for small/diverse groups and failed-batch fallback. Preserve ordered per-event results, event-body hashing, and the existing blocking-worker boundary.

The weighted equation accumulation is adapted locally from Zcash Foundation FROST. Signature preparation is separate from accumulation. The adaptation keeps Nostr's x-only encoding, transcript-bound nonzero coefficients, repeated-author grouping, and k256's multiscalar multiplication. The pinned source, Apache-2.0 attribution, and modifications are documented in NOTICE.md. No FROST dependency or benchmark artifacts are included.

Fresh release measurements on Apple M4 Max (arm64, macOS 26.7.2, Rust 1.98.1) show 1.24–1.43× faster repeated-author verification. Each case used four warmups and seven alternating-order rounds, comparing the previous desktop loop including parsing and result allocation. Signing, IPC, networking, and rendering were excluded. Medians per call:

Signatures Authors Previous loop Adaptive verifier Speedup
12 1 180.7 µs 145.7 µs 1.24×
32 4 482.4 µs 382.2 µs 1.26×
128 4 1,982.1 µs 1,414.0 µs 1.40×
512 4 8,162.2 µs 5,795.5 µs 1.41×

The 128-signature/one-author case reached 1.43×. Small/diverse groups stayed within 2.4% of the original loop in this run. Invalid batches cost approximately 1.8× because they require individual checks after the batch attempt. These are native verification measurements, not whole-app or other-architecture results. Measured verifier SHA-256: 2f039c3fff22a5d2a6071d529b783569d1cd8fd73cf1b46ba5e809a53bf4f12f.

All eight crypto tests pass, including every official BIP-340 vector row (the Nostr API rejects the four non-32-byte messages), mixed vector batches, and seeded mutations/permutations checked against individual libsecp256k1 results. Existing tests cover cancellation attacks and failed-batch fallback; the native async-command integration test also passed. Negative controls using fixed coefficients or excluding signatures from the coefficient seed each fail for the intended forged-signature acceptance. Independent review found no blockers. Mandatory push hooks pass: TypeScript/related frontend tests, design checks, and workspace Clippy. The earlier focused frontend run passed 285 tests.

An earlier full desktop-suite run failed in host_command::tests::stdin_is_exact_data_and_output_is_drained_concurrently and then received SIGSEGV in window_state::tests::onboarding_snapshot_is_kept_until_next_launch_restore on macOS. Those tests were unchanged. A native WKWebView diagnostic exercised catch-up with synthetic signed events through the production IPC verifier. Normal live-relay acceptance, human acceptance, and measurements on other architectures remain outstanding. This PR remains a draft; the local adaptation does not inherit upstream cryptographic audit coverage.

jmecom and others added 4 commits November 11, 2026 15:37
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Jordan Mecom <jm@squareup.com>
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Jordan Mecom <jm@squareup.com>
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Jordan Mecom <jm@squareup.com>
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Jordan Mecom <jm@squareup.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant